我正在尝试实现一个Hibernate会话/事务拦截器,以避免LazyInitializationExceptionStruts2中的json结果出现,但无论如何我都会得到此异常:
LazyInitializationException
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之前甚至trans.commit()和session.close();
trans.commit()
session.close();
好的,最后我解决了将通用DAO注入(带有会话和事务)添加到genericAction的问题。这适用于带有惰性hibernatebean的JSONResults和jsp。
感谢您对“ bmorris591”和“ Roman C”的贡献(我什至不需要,甚至不需要这些插件)。
我留下我的例子,希望我不要忘记任何事情…
拦截器配置(struts.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; } }
一般动作:
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; } }