【问题标题】:Struts 2 Json Result Hibernate LazyInitialization - How to deserialize within a hibernate sessionStruts 2 Json Result Hibernate LazyInitialization - 如何在休眠会话中反序列化
【发布时间】:2013-03-07 11:18:22
【问题描述】:

我正在尝试实现 Hibernate 会话/事务拦截器以避免 Struts2 中 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;
    }

}

这不起作用,我什至在trans.commit()session.close(); 之前得到LazyInitializationException

【问题讨论】:

    标签: java json hibernate struts2 lazy-initialization


    【解决方案1】:

    不要重新实现轮子。如果您需要在视图概念中实现开放会话,请使用Hibernate Full Plugin。如果你想修复 LazyInitializationExceptionFetchType.EAGER 放在集合上。

    【讨论】:

    • 感谢回答,我去看看插件!
    【解决方案2】:

    好的,我终于解决了将通用 DAO(带有会话和事务)注入到 genericAction 的问题。这适用于带有惰性休眠 bean 的 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;
        }
    
    }
    

    我的行动:

    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;
        }
    }
    

    【讨论】:

    • +1 用于使用 JSON 注释。相信它有效,您是否在模型属性方法上尝试过?
    • 这个 @JSON(deserialize=false, serialize=false) 是为了不序列化 DAO 的子构件在 struts 动作上。我不能把它放在模型对象中,没有意义。
    • 好的,我正在寻找一些机制来从序列化/反序列化中排除属性,这样它就不会像 flexjson 那样影响 hibernate 中的延迟加载实体。
    • 您可以在模型对象属性上使用它(也可以考虑瞬态属性)
    【解决方案3】:

    如果这是一个 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,这样您就不会拥有所有的空方法。

    【讨论】:

    • 感谢您的回答和更正。但我的问题是:为什么我在调用 JSONUtil->JSONWriter 的调用()中得到 LazyInitializationException,当事务和会话处于活动状态时???
    猜你喜欢
    • 1970-01-01
    • 2016-03-11
    • 2012-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-05
    • 2015-01-03
    相关资源
    最近更新 更多