简体   繁体   English

初始化延迟集合

[英]Initialize lazy collections

I'm developing a Struts2 + Spring + Hibernate webapp and I need to initialize a lazy collection after retrieving an object or a collection of that object. 我正在开发一个Struts2 + Spring + Hibernate webapp,我需要在检索一个对象或该对象的集合后初始化一个惰性集合。

Use case 用例

I have a team model with a relation eagerly loaded called employees (I think it's obvious that this is a collection). 我有一个团队模型,其中一个关系急切地被称为员工 (我认为很明显这是一个集合)。 In turn, employee model has a lazy relation registry that I need just for some specific actions so I don't need at all to load it eagerly. 反过来, 员工模型有一个懒惰的关系注册表 ,我只需要一些特定的操作,所以我根本不需要急切地加载它。

Now. 现在。 I call my teamService (injected to my Struts2 controller with Spring) in order to retrieve a specific teamItem which has already his collection employees loaded. 我调用我的teamService (用Spring注入我的Struts2控制器),以便检索已加载其集合员工的特定teamItem Now it's time to load for each employee its registry relation. 现在是时候为每个员工加载其注册表关系了。

Using the employeeService (also this injected to my Struts2 controller with Spring) I call the initializeCollections() method of his DAO that should load the lazy collection calling 使用employeeService (也用Spring注入我的Struts2控制器)我调用他的DAO的initializeCollections()方法,它应该加载延迟集合调用

Hibernate.initialize(employee.getRegistry());

When I perform this action a org.hibernate.LazyInitializationException: could not initialize proxy - no Session exception is thrown. 当我执行此操作时, org.hibernate.LazyInitializationException: could not initialize proxy - no Session引发org.hibernate.LazyInitializationException: could not initialize proxy - no Session异常。

stack trace: 堆栈跟踪:

at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:167) ~[hibernate-core-3.6.10.Final.jar:3.6.10.Final]
at org.hibernate.Hibernate.initialize(Hibernate.java:414) ~[hibernate-core-3.6.10.Final.jar:3.6.10.Final]
at web.bkgd.simba.dao.registry.RegistryEmployeeDAO.initializeCollections(RegistryEmployeeDAO.java:438) ~[RegistryEmployeeDAO.class:?]
at web.bkgd.simba.service.abstractions.BaseService.initializeCollections(BaseService.java:142) ~[BaseService.class:?]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.7.0_79]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) ~[?:1.7.0_79]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.7.0_79]
at java.lang.reflect.Method.invoke(Method.java:606) ~[?:1.7.0_79]
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317) ~[spring-aop-4.1.0.RELEASE.jar:4.1.0.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) ~[spring-aop-4.1.0.RELEASE.jar:4.1.0.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) ~[spring-aop-4.1.0.RELEASE.jar:4.1.0.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:98) ~[spring-tx-4.1.0.RELEASE.jar:4.1.0.RELEASE]
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:266) ~[spring-tx-4.1.0.RELEASE.jar:4.1.0.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95) ~[spring-tx-4.1.0.RELEASE.jar:4.1.0.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.1.0.RELEASE.jar:4.1.0.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207) ~[spring-aop-4.1.0.RELEASE.jar:4.1.0.RELEASE]
at com.sun.proxy.$Proxy1302.initializeCollections(Unknown Source) ~[?:?]
at web.bkgd.simba.controller.ajax.agenda.TeamController.doSomething(TeamController.java:177) ~[AjaxTeamController.class:?]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.7.0_79]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) ~[?:1.7.0_79]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.7.0_79]
at java.lang.reflect.Method.invoke(Method.java:606) ~[?:1.7.0_79]
at ognl.OgnlRuntime.invokeMethod(OgnlRuntime.java:870) ~[ognl-3.0.6.jar:?]
at ognl.OgnlRuntime.callAppropriateMethod(OgnlRuntime.java:1293) ~[ognl-3.0.6.jar:?]
at ognl.ObjectMethodAccessor.callMethod(ObjectMethodAccessor.java:68) ~[ognl-3.0.6.jar:?]
at com.opensymphony.xwork2.ognl.accessor.XWorkMethodAccessor.callMethodWithDebugInfo(XWorkMethodAccessor.java:117) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
at com.opensymphony.xwork2.ognl.accessor.XWorkMethodAccessor.callMethod(XWorkMethodAccessor.java:108) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
at ognl.OgnlRuntime.callMethod(OgnlRuntime.java:1369) ~[ognl-3.0.6.jar:?]
at ognl.ASTMethod.getValueBody(ASTMethod.java:90) ~[ognl-3.0.6.jar:?]
at ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212) ~[ognl-3.0.6.jar:?]
at ognl.SimpleNode.getValue(SimpleNode.java:258) ~[ognl-3.0.6.jar:?]
at ognl.Ognl.getValue(Ognl.java:494) ~[ognl-3.0.6.jar:?]
at ognl.Ognl.getValue(Ognl.java:458) ~[ognl-3.0.6.jar:?]
at com.opensymphony.xwork2.ognl.OgnlUtil$2.execute(OgnlUtil.java:309) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
at com.opensymphony.xwork2.ognl.OgnlUtil.compileAndExecute(OgnlUtil.java:340) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
at com.opensymphony.xwork2.ognl.OgnlUtil.getValue(OgnlUtil.java:307) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
at com.opensymphony.xwork2.DefaultActionInvocation.invokeAction(DefaultActionInvocation.java:423) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
at com.opensymphony.xwork2.DefaultActionInvocation.invokeActionOnly(DefaultActionInvocation.java:287) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:250) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
at web.bkgd.simba.utility.interceptors.SessionCleanInterceptor.intercept(SessionCleanInterceptor.java:86) ~[SessionCleanInterceptor.class:?]
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
at org.apache.struts2.interceptor.DeprecationInterceptor.intercept(DeprecationInterceptor.java:41) ~[struts2-core-2.3.24.1.jar:2.3.24.1]
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
at org.apache.struts2.interceptor.debugging.DebuggingInterceptor.intercept(DebuggingInterceptor.java:256) ~[struts2-core-2.3.24.1.jar:2.3.24.1]
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
at com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor.doIntercept(DefaultWorkflowInterceptor.java:167) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
at com.opensymphony.xwork2.validator.ValidationInterceptor.doIntercept(ValidationInterceptor.java:265) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
at org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor.doIntercept(AnnotationValidationInterceptor.java:76) ~[struts2-core-2.3.24.1.jar:2.3.24.1]
at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
at com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor.intercept(ConversionErrorInterceptor.java:138) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:229) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:229) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
at com.opensymphony.xwork2.interceptor.StaticParametersInterceptor.intercept(StaticParametersInterceptor.java:191) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
at org.apache.struts2.interceptor.MultiselectInterceptor.intercept(MultiselectInterceptor.java:73) ~[struts2-core-2.3.24.1.jar:2.3.24.1]
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
at org.apache.struts2.interceptor.DateTextFieldInterceptor.intercept(DateTextFieldInterceptor.java:125) ~[struts2-core-2.3.24.1.jar:2.3.24.1]
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
at org.apache.struts2.interceptor.CheckboxInterceptor.intercept(CheckboxInterceptor.java:91) ~[struts2-core-2.3.24.1.jar:2.3.24.1]
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
at org.apache.struts2.interceptor.FileUploadInterceptor.intercept(FileUploadInterceptor.java:253) ~[struts2-core-2.3.24.1.jar:2.3.24.1]
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
at com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor.intercept(ModelDrivenInterceptor.java:100) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
at com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor.intercept(ScopedModelDrivenInterceptor.java:141) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
at com.opensymphony.xwork2.interceptor.ChainingInterceptor.intercept(ChainingInterceptor.java:145) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
at com.opensymphony.xwork2.interceptor.PrepareInterceptor.doIntercept(PrepareInterceptor.java:171) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
at com.opensymphony.xwork2.interceptor.I18nInterceptor.intercept(I18nInterceptor.java:139) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
at org.apache.struts2.interceptor.ServletConfigInterceptor.intercept(ServletConfigInterceptor.java:164) ~[struts2-core-2.3.24.1.jar:2.3.24.1]
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
at com.opensymphony.xwork2.interceptor.AliasInterceptor.intercept(AliasInterceptor.java:193) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
at com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor.intercept(ExceptionMappingInterceptor.java:189) [xwork-core-2.3.24.1.jar:2.3.24.1]
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) [xwork-core-2.3.24.1.jar:2.3.24.1]
at web.bkgd.simba.utility.interceptors.LoginInterceptor.intercept(LoginInterceptor.java:113) [LoginInterceptor.class:?]
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) [xwork-core-2.3.24.1.jar:2.3.24.1]
at org.apache.struts2.impl.StrutsActionProxy.execute(StrutsActionProxy.java:54) [struts2-core-2.3.24.1.jar:2.3.24.1]
at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:564) [struts2-core-2.3.24.1.jar:2.3.24.1]
at org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:81) [struts2-core-2.3.24.1.jar:2.3.24.1]
at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:99) [struts2-core-2.3.24.1.jar:2.3.24.1]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) [catalina.jar:7.0.61]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) [catalina.jar:7.0.61]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220) [catalina.jar:7.0.61]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122) [catalina.jar:7.0.61]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505) [catalina.jar:7.0.61]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170) [catalina.jar:7.0.61]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103) [catalina.jar:7.0.61]
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950) [catalina.jar:7.0.61]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116) [catalina.jar:7.0.61]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:423) [catalina.jar:7.0.61]
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1079) [tomcat-coyote.jar:7.0.61]
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:620) [tomcat-coyote.jar:7.0.61]
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:318) [tomcat-coyote.jar:7.0.61]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [?:1.7.0_79]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [?:1.7.0_79]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-coyote.jar:7.0.61]
at java.lang.Thread.run(Thread.java:745) [?:1.7.0_79]
  • Am I doing something wrong? 难道我做错了什么?
  • Is there a different way to load that lazy collection? 是否有不同的方式来加载这个懒惰的集合?

EDIT 01-12-2015 编辑01-12-2015

I've tried to follow Predrag Maric answer and I have a little edit to do since seems still not working. 我试图按照Predrag Maric的回答,我做了一些编辑,因为似乎仍然无法正常工作。

So: 所以:

  1. Implement Open Session in View pattern 在View模式中实现Open Session

No way. 没门。 This solution may cause a very deep loading of the relations expecially for JSON serialization. 此解决方案可能会导致非常深的关系加载,特别是对于JSON序列化。 Of course I can always define the <param name="includeProperties"> tag and load just what I need, but I'm still a little scared of the performances. 当然我总是可以定义<param name="includeProperties">标签并加载我需要的东西,但我仍然有点害怕表演。

  1. Initialize whatever you need in the first service 在第一个服务中初始化您需要的任何内容

And here is the point. 这就是重点。 I've changed my action and DAO structure in order to implement this function. 我已经改变了我的动作和DAO结构以实现这个功能。 I've used a little of reflection in order to create a general method that I can use in every single DAO of my application. 我已经使用了一些反射来创建一个通用的方法,我可以在我的应用程序的每个DAO中使用。

How it works is very simple: 它的工作原理非常简单:

Example

INPUT: INPUT:

  • beanClass: Team beanClass:团队
  • model: team with no relations loaded model:没有加载关系的团队
  • relations: List:{"relation", "relation.childRelation.grandChildRelation"} 关系:List:{“relation”,“relation.childRelation.grandChildRelation”}

The method for the first string simply calls Hibernate.initialize() method and for the second one splits the string in order to load: 第一个字符串的方法只调用Hibernate.initialize()方法,第二个字符串拆分字符串以加载:

  • realation, returns initializeRelations(relation.class, relation, "childRelation.grandChildRelation"); realation,返回initializeRelations(relation.class, relation, "childRelation.grandChildRelation");
  • childRelation, returns initializeRelations(childRelation.class, childRelation, "grandChildRelation"); childRelation,返回initializeRelations(childRelation.class, childRelation, "grandChildRelation");
  • grandChildRelation; grandChildRelation;

Here you have the code: 在这里你有代码:

TEAM DAO TEAM DAO

These methods are called after a team bean or a list of team beans has been loaded from the database 在从数据库加载团队bean或团队bean列表之后调用这些方法

/**
 * Initialize relations. This method returns true if a correct
 * initialization of the relation has been made by hibernate, false in any
 * other case. If the relations object is a List, the method recursively
 * call himself in order to initialize every single instance of the list.
 * If the relations string contains a "." it means that a grandchild
 * relation has to be loaded.
 *
 * @param beanClass
 * @param model
 * @param relations
 * @return boolean
 */
public boolean initializeRelations(Class beanClass, BaseModel model, Object relations) {
    // Check if relations is a List
    if (relations instanceof List) {
        // Recursively call initializeRelations
        for (String relation : (List<String>) relations) {
            return initializeRelations(beanClass, model, relation);
        }
    } else if (relations instanceof String) {
        // If relations contains "." then a grandChild relation has to be loaded.
        if (((String) relations).contains(".")) {
            String[] childRelations = ((String) relations).split("\\.");

            // Initialize the child relation
            Object newChildRelations = initializeRelation(beanClass, model, childRelations[0]);

            if (newChildRelations == null) {
                return false;
            } else if (newChildRelations instanceof BaseModel) {
                initializeRelations(newChildRelations.getClass(), model, (Object[]) Arrays.copyOfRange(childRelations, 1, childRelations.length));
            } else if (newChildRelations instanceof List) {
                for (Object newChildRelation : childRelations) {
                    initializeRelations(newChildRelation.getClass(), model, (Object[]) Arrays.copyOfRange(childRelations, 1, childRelations.length));
                }
            }
        } else {
            Object newChildRelations = initializeRelation(beanClass, model, (String) relations);

            return newChildRelations == null;
        }
    }

    return false;
}

private Object initializeRelation(Class beanClass, BaseModel model, String relation) {
    try {
        for (PropertyDescriptor pd : Introspector.getBeanInfo(beanClass).getPropertyDescriptors()) {
            if (pd.getReadMethod() != null && !"class".equals(pd.getName()) && relation.toLowerCase().equals(pd.getName().toLowerCase()) && pd.getReadMethod().invoke(model) == null) {
                Hibernate.initialize(pd.getReadMethod().invoke(model));

                return pd.getReadMethod().invoke(model);
            }
        }
    } catch (IntrospectionException ex) {
        LOG.warn("Cannot initialize ralation", ex);
    } catch (HibernateException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
        LOG.warn("Cannot initialize ralation", ex);
    }
    return null;
}

But what I see in my log is that just the first relation is loaded 但是我在日志中看到的只是加载了第一个关系

[DEBUG] 01-12-2015 14:06:52 Controller - relation: Employee{data1="data1", data2="data2", data3="data3", data4="data4", data5="data5"}
[DEBUG] 01-12-2015 14:06:52 Controller - child: [!!!model.Registry_$$_javassist_17@75ce9b7d=>org.hibernate.LazyInitializationException:could not initialize proxy - no Session!!!]

Yes, you can use Hibernate.initialize() to initialize lazy relations, but this requires an active Hibernate session. 是的,您可以使用Hibernate.initialize()来初始化延迟关系,但这需要一个活动的Hibernate会话。 You are 你是

  1. Calling teamService from the controller (one transaction) 从控制器调用teamService (一个事务)
  2. Calling employeeService with the results of the first call (another transaction) 使用第一次调用的结果调用employeeService (另一个事务)

Your entities are detached from the session after the first call (correct me if I'm wrong, I assumed you've configured transactions on service layer), so this fails. 第一次调用后,您的实体与会话分离(如果我错了,请更正我,我假设您已在服务层上配置了事务),因此失败。 You should either 你也应该

  1. Implement Open Session in View pattern 在View模式中实现Open Session
  2. Initialize whatever you need in the first service 在第一个服务中初始化您需要的任何内容

As for 2., if this service is used in other places which don't need employee.registry initialized, you can use a parameter to control initialization 对于2.,如果此服务用于其他不需要employee.registry初始化的地方,则可以使用参数来控制初始化

teamService.getTeam(id, init);
// and then in getTeam()
if (init) {
    Hibernate.initialize(employee.getRegistry());
}

To make this more generic, you can create a InitConfig class, which would be passed to each service that needs this kind of behavior. 为了使其更通用,您可以创建一个InitConfig类,该类将传递给需要此类行为的每个服务。 You just add specific parameters in it as you need them. 您只需在需要时添加特定参数即可。

public class InitConfig {
    ...
    private boolean initRegistry;
    ...
}

teamService.getTeam(id, initConfig);
// and then in getTeam()
if (initConfig.getInitRegistry()) {
    Hibernate.initialize(employee.getRegistry());
}

I had the some problem a few months ago. 几个月前我遇到了一些问题。 I have solved it setting a parameter in my session factory builder. 我已经解决了它在我的会话工厂构建器中设置参数的问题。

Try setting the parameter "hibernate.enable_lazy_load_no_trans" to your hibernate config. 尝试将参数“hibernate.enable_lazy_load_no_trans”设置为您的hibernate配置。

sfBuilder.getProperties().put("hibernate.enable_lazy_load_no_trans",
            "true");

This parameter solved my problem. 这个参数解决了我的问题。 Hope it helps. 希望能帮助到你。

Edited: Use with caution. 编辑:谨慎使用。 Check out this post . 看看这篇文章

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM