2013-03-07 61 views
3

我想實現一個Hibernate會話/事務攔截器,以避免在Struts2 JSON結果LazyInitializationException內反序列化,但無論如何,我得到這個異常:Struts 2的JSON結果Hibernate的惰性初始模式 - 如何將Hibernate的Session

245968 [http-8080-7] ERROR util.HibernateEndTransInterceptor - org.apache.struts2.json.JSONException: org.apache.struts2.json.JSONException: org.apache.struts2.json.JSONException: org.apache.struts2.json.JSONException: java.lang.reflect.InvocationTargetException 
org.apache.struts2.json.JSONException: org.apache.struts2.json.JSONException: org.apache.struts2.json.JSONException: org.apache.struts2.json.JSONException: java.lang.reflect.InvocationTargetException 
    at org.apache.struts2.json.JSONWriter.bean(JSONWriter.java:238) 
    at org.apache.struts2.json.JSONWriter.processCustom(JSONWriter.java:171) 
    at org.apache.struts2.json.JSONWriter.process(JSONWriter.java:161) 
    at org.apache.struts2.json.JSONWriter.value(JSONWriter.java:127) 
    at org.apache.struts2.json.JSONWriter.write(JSONWriter.java:95) 
    at org.apache.struts2.json.JSONUtil.serialize(JSONUtil.java:116) 
    at org.apache.struts2.json.JSONResult.createJSONString(JSONResult.java:196) 
    at org.apache.struts2.json.JSONResult.execute(JSONResult.java:170) 
    at com.opensymphony.xwork2.DefaultActionInvocation.executeResult(DefaultActionInvocation.java:374) 
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:278) 
    at util.HibernateEndTransInterceptor.intercept(HibernateEndTransInterceptor.java:55) 
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249) 
    at org.apache.struts2.interceptor.debugging.DebuggingInterceptor.intercept(DebuggingInterceptor.java:256) 
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249) 
    at com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor.doIntercept(DefaultWorkflowInterceptor.java:176) 
    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98) 
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249) 
    at com.opensymphony.xwork2.validator.ValidationInterceptor.doIntercept(ValidationInterceptor.java:265) 
    at org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor.doIntercept(AnnotationValidationInterceptor.java:68) 
    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98) 
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249) 
    at com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor.intercept(ConversionErrorInterceptor.java:138) 
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249) 
    at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:236) 
    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98) 
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249) 
    at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:236) 
    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98) 
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249) 
    at com.opensymphony.xwork2.interceptor.StaticParametersInterceptor.intercept(StaticParametersInterceptor.java:190) 
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249) 
    at org.apache.struts2.interceptor.MultiselectInterceptor.intercept(MultiselectInterceptor.java:75) 
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249) 
    at org.apache.struts2.interceptor.CheckboxInterceptor.intercept(CheckboxInterceptor.java:90) 
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249) 
    at org.apache.struts2.interceptor.FileUploadInterceptor.intercept(FileUploadInterceptor.java:243) 
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249) 
    at com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor.intercept(ModelDrivenInterceptor.java:100) 
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249) 
    at com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor.intercept(ScopedModelDrivenInterceptor.java:141) 
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249) 
    at com.opensymphony.xwork2.interceptor.ChainingInterceptor.intercept(ChainingInterceptor.java:145) 
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249) 
    at com.opensymphony.xwork2.interceptor.PrepareInterceptor.doIntercept(PrepareInterceptor.java:171) 
    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98) 
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249) 
    at com.opensymphony.xwork2.interceptor.I18nInterceptor.intercept(I18nInterceptor.java:176) 
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249) 
    at org.apache.struts2.interceptor.ServletConfigInterceptor.intercept(ServletConfigInterceptor.java:164) 
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249) 
    at com.opensymphony.xwork2.interceptor.AliasInterceptor.intercept(AliasInterceptor.java:192) 
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249) 
    at com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor.intercept(ExceptionMappingInterceptor.java:187) 
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249) 
    at util.HibernateBeginTransInterceptor.intercept(HibernateBeginTransInterceptor.java:32) 
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249) 
    at util.LoginInterceptor.intercept(LoginInterceptor.java:36) 
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249) 
    at org.apache.struts2.impl.StrutsActionProxy.execute(StrutsActionProxy.java:54) 
    at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:511) 
    at org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:77) 
    at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:91) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173) 
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213) 
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178) 
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126) 
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105) 
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107) 
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148) 
    at org.apache.coyote.http11.Http11AprProcessor.process(Http11AprProcessor.java:831) 
    at org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Http11AprProtocol.java:652) 
    at org.apache.tomcat.util.net.AprEndpoint$Worker.run(AprEndpoint.java:1203) 
    at java.lang.Thread.run(Thread.java:722) 
Caused by: org.apache.struts2.json.JSONException: org.apache.struts2.json.JSONException: org.apache.struts2.json.JSONException: java.lang.reflect.InvocationTargetException 
    at org.apache.struts2.json.JSONWriter.bean(JSONWriter.java:238) 
    at org.apache.struts2.json.JSONWriter.processCustom(JSONWriter.java:171) 
    at org.apache.struts2.json.JSONWriter.process(JSONWriter.java:161) 
    at org.apache.struts2.json.JSONWriter.value(JSONWriter.java:127) 
    at org.apache.struts2.json.JSONWriter.add(JSONWriter.java:363) 
    at org.apache.struts2.json.JSONWriter.bean(JSONWriter.java:223) 
    ... 73 more 
Caused by: org.apache.struts2.json.JSONException: org.apache.struts2.json.JSONException: java.lang.reflect.InvocationTargetException 
    at org.apache.struts2.json.JSONWriter.bean(JSONWriter.java:238) 
    at org.apache.struts2.json.JSONWriter.processCustom(JSONWriter.java:171) 
    at org.apache.struts2.json.JSONWriter.process(JSONWriter.java:161) 
    at org.apache.struts2.json.JSONWriter.value(JSONWriter.java:127) 
    at org.apache.struts2.json.JSONWriter.add(JSONWriter.java:363) 
    at org.apache.struts2.json.JSONWriter.bean(JSONWriter.java:223) 
    ... 78 more 
Caused by: org.apache.struts2.json.JSONException: java.lang.reflect.InvocationTargetException 
    at org.apache.struts2.json.JSONWriter.bean(JSONWriter.java:238) 
    at org.apache.struts2.json.JSONWriter.processCustom(JSONWriter.java:171) 
    at org.apache.struts2.json.JSONWriter.process(JSONWriter.java:161) 
    at org.apache.struts2.json.JSONWriter.value(JSONWriter.java:127) 
    at org.apache.struts2.json.JSONWriter.add(JSONWriter.java:363) 
    at org.apache.struts2.json.JSONWriter.bean(JSONWriter.java:223) 
    ... 83 more 
Caused by: java.lang.reflect.InvocationTargetException 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:601) 
    at org.apache.struts2.json.JSONWriter.bean(JSONWriter.java:218) 
    ... 88 more 
Caused by: org.hibernate.LazyInitializationException: could not initialize proxy - no Session 
    at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:165) 
    at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:272) 
    at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:185) 
    at com.lm.model.common.Language_$$_javassist_0.getName(Language_$$_javassist_0.java) 
    ... 93 more 

我的攔截器看起來是這樣的:

package util; 

import java.util.Map; 

import org.apache.log4j.Logger; 
import org.hibernate.Session; 
import org.hibernate.SessionFactory; 
import org.hibernate.Transaction; 

import util.hibernate.HibernateUtil; 

import com.lm.action.ActionsConstants; 
import com.lm.action.user.Constants; 
import com.opensymphony.xwork2.ActionInvocation; 
import com.opensymphony.xwork2.interceptor.Interceptor; 

public class HibernateEndTransInterceptor implements Interceptor, Constants, ActionsConstants { 


    private static final long serialVersionUID = -8734958511612355789L; 

    private static SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); 
    private transient Logger log = Logger.getLogger(HibernateEndTransInterceptor.class); 
    private Session s=null; 
    private Transaction t=null; 

    @Override 
    public void destroy() { 
    } 

    @Override 
    public void init() { 
    } 

    @Override 
    public String intercept(final ActionInvocation invocation) throws Exception { 
     /*invocation.addPreResultListener(new PreResultListener() { 

      @Override 
      public void beforeResult(ActionInvocation arg0, String arg1) { 
       Map<String, ResultConfig> resultsMap = invocation.getProxy().getConfig().getResults(); 
       //ResultConfig finalResultConfig = resultsMap.get(resultCode); 

      } 
     });*/ 


     Map<String,Object> strutsSession = invocation.getInvocationContext().getSession(); 
     String res=null; 
     try { 
      s=sessionFactory.openSession(); 
      t = s.beginTransaction(); 
      strutsSession.put("hibernateSession", s); 
      strutsSession.put("hibernateTransaction", t); 
      res=invocation.invoke(); 
      t.commit(); 
     } catch (Throwable t2) { 
      log.error(t2,t2); 
      try { 
       t.rollback(); 
      } catch (Throwable t3) { 
       log.error(t3,t3); 
      } 
     } finally { 
      try { 
       s.close(); 
      } catch (Throwable t) { 
       log.error(t,t); 
      } 
      strutsSession.remove("hibernateSession"); 
      strutsSession.remove("hibernateTransaction"); 
     } 
     return res; 
    } 

} 

這不是工作,我越來越LazyInitializationException甚至在和session.close();

回答

1

好吧,最後我解決了通用DAO(與會話和事務)的注入添加到genericAction。這適用於JSONResults &帶有惰性Bean的jsp。

感謝您對「bmorris591」和「Roman C」的貢獻(我不想,甚至不需要,所有插件)。

我離開我的例子,我希望我不會忘記任何事......

攔截器配置(支柱。XML片段):

<package name="lmp" extends="struts-default,json-default"> 
    <interceptors> 
     <interceptor name="login" class="util.LoginInterceptor"/> 
     <interceptor name="hibernateSessionTransInjector" class="util.HibernateSessionTransInjectorInterceptor"/> 
     <interceptor-stack name="loggingStack"> 
      <interceptor-ref name="login" /> 
      <interceptor-ref name="defaultStack" /> 
      <interceptor-ref name="hibernateSessionTransInjector"/> 
     </interceptor-stack> 
    </interceptors> 

    <default-interceptor-ref name="loggingStack"/> 

    <global-results> 
     <result name="login" type="redirectAction">login</result> 
    </global-results> 
</package> 
<package name="myAction" extends="lmp"> 

    <action name="myAction" class="com.lmp.MyAction"> 
     <result name="json" type="json"> 
      <param name="ignoreHierarchy">false</param> 
     </result> 
     <result name="*">/jsp/myAction.jsp</result> 
    </action> 
</package> 

攔截器實現:

package util; 

import org.apache.log4j.Logger; 
import org.hibernate.Session; 
import org.hibernate.SessionFactory; 

import util.hibernate.HibernateUtil; 

import com.lm.action.ActionsConstants; 
import com.lm.action.user.Constants; 
import com.lm.dao.DAO; 
import com.opensymphony.xwork2.ActionInvocation; 
import com.opensymphony.xwork2.interceptor.Interceptor; 

public class HibernateSessionTransInjectorInterceptor implements Interceptor, Constants, ActionsConstants { 


    private static final long serialVersionUID = -8734958511612355789L; 

    private static SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); 
    private transient Logger log = Logger.getLogger(HibernateSessionTransInjectorInterceptor.class); 

    @Override 
    public void destroy() { 
    } 

    @Override 
    public void init() { 
    } 

    @Override 
    public String intercept(final ActionInvocation invocation) throws Exception { 
     String res=null; 
     DAO dao=null; 
     try { 
      Session s=sessionFactory.openSession(); 
      dao = new DAO(s); 
      dao.beginTransaction(); 
      **invocation.getStack().setValue("dao", dao, true);** 
      res=invocation.invoke(); 
      boolean rollback=(Boolean)invocation.getStack().findValue("rollbackTransaction", Boolean.class); 
      if (rollback) 
       dao.rollBackTransaction(); 
      if (!dao.getT().wasRolledBack()) 
       dao.commitTransaction(); 
     } catch (Throwable t2) { 
      log.error(t2,t2); 
      if (dao!=null) 
      try { 
       dao.rollBackTransaction(); 
      } catch (Throwable t3) { 
       log.error(t3,t3); 
      } 
     } finally { 
      if (dao!=null) 
      try { 
       dao.finallyClose(); 
      } catch (Throwable t) { 
       log.error(t,t); 
      } 
     } 
     return res; 
    } 

} 

UserDAO的例子:

public class UserDAO extends DAO { 

[...] 
    public UserDAO(Session s) { 
     super(s); 
    } 
[...] 
} 

GenericDAO例如:

public class DAO { 

    protected static final transient Logger log = Logger.getLogger(DAO.class); 

    public static SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); 
    public Session s = null; 
    public Transaction t = null; 

    public DAO(Session s) { 
     this.s=s; 
    } 

    public void beginTransaction(Transaction t) { 
     this.t=t; 
    } 

    private int exceptionErr=0; 
    public void beginTransaction() { 
     try { 
      t=s.beginTransaction(); 
     } catch (Throwable t) { 
      log.error(t,t); 
     } 
    } 
    public void rollBackTransaction() { 
     if (t!=null && t.isActive()) 
      t.rollback(); 
    } 
    public void commitTransaction() { 
     if (t!=null && t.isActive()) 
      t.commit(); 
    } 

    public void finallyClose() { 
     if (t!=null && t.isActive()) 
      t.rollback(); 
     if (s!=null && s.isOpen()) 
      s.close(); 
    } 

    public Session getS() { 
     return s; 
    } 

    public void setS(Session s) { 
     this.s = s; 
    } 

    public Transaction getT() { 
     return t; 
    } 

    public void setT(Transaction t) { 
     this.t = t; 
    } 

} 

GenericAction:

public class GenericAction extends ActionSupport { 

    private DAO dao=null; //Interceptor injects here 

    public GenericAction() { 
    } 

... 
    @JSON(deserialize=false, serialize=false) 
    public DAO getDao() { 
     return dao; 
    } 

    @JSON(deserialize=false, serialize=false) 
    public void setDao(DAO dao) { 
     this.dao = dao; 
    } 

} 

MyAction:

public class MyAction extends GenericAction { 

    public MyAction() { 
    } 

    @Override 
    public String execute() throws Exception { 
     super.execute(); 
     UserDAO userDAO=new UserDAO(getDao().getS()); 
     OtherDAO otherDAO=new OtherDAO(getDao().getS()); 
     userDAO.loadUsers(...); 
      return SUCCESS; 
    } 
} 
+0

使用JSON註釋的+1。相信它的工作原理,你是否嘗試過模型屬性方法? – 2013-03-31 08:41:03

+0

這個@JSON(deserialize = false,serialize = false)是爲了不在struts操作上序列化DAO的孩子工件。我無法把它放在模型對象中,沒有任何意義。 – surfealokesea 2013-04-02 10:29:22

+0

好吧,我正在尋找一些排除序列化/反序列化屬性的機制,所以它不會像flexjson那樣影響休眠中的延遲加載實體。 – 2013-04-02 12:15:05

0

如果這是一個Struts2攔截器,這是絕對不是的實現方式。

應用具有攔截的對所有請求這樣一個請求被設定可變的intercept方法然後另一個進來和復位它們而第一仍在處理的單個實例。第一個請求隨後在第二個請求的會話上通過呼叫session.close()返回。

你應該攔截器看起來更像是這樣的:

@Override 
public String intercept(final ActionInvocation invocation) throws Exception { 
    final Map<String, Object> strutsSession = invocation.getInvocationContext().getSession(); 
    String res = null; 
    Session s = null; 
    Transaction t = null; 
    try { 
     s = sessionFactory.openSession(); 
     t = s.beginTransaction(); 
     strutsSession.put("hibernateSession", s); 
     strutsSession.put("hibernateTransaction", t); 
     res = invocation.invoke(); 
     t.commit(); 
    } catch (Throwable t2) { 
     log.error(t2, t2); 
     t.rollback(); 
    } finally { 
     s.close(); 
     strutsSession.remove("hibernateSession"); 
     strutsSession.remove("hibernateTransaction"); 
    } 
    return res; 
} 

通知所有變量都是本地,除非你想他們跨請求共享。

另外,最好的做法是擴展AbstractInterceptor,這樣你就沒有所有的空方法了。

+0

謝謝你的回答和改正。但我的問題是:爲什麼我得到LazyInitializationException invoke()誰調用JSONUtil-> JSONWriter當事務和會話是活的? – surfealokesea 2013-03-07 14:27:08

1

不要重新執行weel。如果您需要在查看概念中實施公開會話,請使用Hibernate Full Plugin。如果您想修復LazyInitializationExceptionFetchType.EAGER放在集合上。

+0

感謝您的回答,我會看看插件! – surfealokesea 2013-03-07 14:26:08

相關問題