我正在开发一个Struts2 + Spring + Hibernate webapp,我需要在检索一个对象或该对象的集合后初始化一个惰性集合。
用例
我有一个团队模型,其中包含一个名为员工的热切关系(我认为很明显这是一个集合)。反过来,员工模型有一个懒惰的关系注册表,我只需要一些特定的操作,所以我根本不需要急切地加载它。
现在。我调用我的teamService
(用Spring注入我的Struts2控制器),以便检索已经加载了员工集合的特定teamItem
。现在是时候为每个员工加载其注册表关系了。
使用employeeService
(也用Spring注入我的Struts2控制器)我调用他的DAO的initializeCollections()
方法,该方法应该加载延迟的集合调用
Hibernate.initialize(employee.getRegistry());
当我执行此操作时,会抛出org.hibernate.LazyInitializationException: could not initialize proxy - no Session
异常。
堆栈跟踪:
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]
编辑01-12-2015
我已经尝试过关注 Predrag Maric 的答案,我还有一些编辑要做,因为它似乎仍无效。
所以:
- 以视图模式实施开放会话
醇>
没办法。此解决方案可能会导致非常深的关系加载,特别是对于JSON序列化。当然,我总是可以定义<param name="includeProperties">
标签并加载我需要的内容,但我仍然有点害怕表演。
- 在第一次服务中初始化您需要的任何内容
醇>
这就是重点。我已经改变了我的动作和DAO结构以实现这个功能。我已经使用了一些反射来创建一个通用的方法,我可以在我的应用程序的每个DAO中使用它。
它是如何工作的非常简单:
示例
INPUT:
第一个字符串的方法只调用Hibernate.initialize()
方法,而第二个字符串则拆分字符串以便加载:
initializeRelations(relation.class, relation, "childRelation.grandChildRelation");
initializeRelations(childRelation.class, childRelation, "grandChildRelation");
这里有代码:
TEAM DAO
在从数据库
加载团队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;
}
但是我在日志中看到的只是加载了第一个关系
[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!!!]
答案 0 :(得分:3)
是的,您可以使用Hibernate.initialize()
来初始化延迟关系,但这需要一个活跃的Hibernate会话。你是
teamService
(一次交易)employeeService
第一次调用后,您的实体与会话分离(如果我错了,请更正我,我假设您已在服务层上配置了事务),因此失败。你应该
对于2.,如果此服务用于其他不需要employee.registry
初始化的地方,则可以使用参数来控制初始化
teamService.getTeam(id, init);
// and then in getTeam()
if (init) {
Hibernate.initialize(employee.getRegistry());
}
为了使其更通用,您可以创建一个InitConfig
类,该类将传递给需要此类行为的每个服务。您只需在需要时添加特定参数。
public class InitConfig {
...
private boolean initRegistry;
...
}
teamService.getTeam(id, initConfig);
// and then in getTeam()
if (initConfig.getInitRegistry()) {
Hibernate.initialize(employee.getRegistry());
}
答案 1 :(得分:3)
尝试设置参数&#34; hibernate.enable_lazy_load_no_trans&#34;你的hibernate配置。
sfBuilder.getProperties().put("hibernate.enable_lazy_load_no_trans",
"true");
这个参数解决了我的问题。希望它有所帮助。
编辑: 谨慎使用。查看this post。