问题内容:
在通过懒加载的方式通过代理对象获取一个model类的多对一的关联配置的时候报如下错误:
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:164)
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:285)
at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:185)
at com.bwol.pm.project.entity.FlowComb_$$_javassist_38.getFlowList(FlowComb_$$_javassist_38.java)
at com.bwol.common.controller.IndexController.topSelectChange(IndexController.java:868)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
public class IndexController extends SpringControllerSupport{
Milestone mileStone = this.getMilestoneBySession();
List<FlowFlow> flowList = mileStone.getFlowComb().getFlowList();
}
hibernate的配置
<class name="com.bwol.pm.project.entity.Milestone" table="T_PROJECT_MILESTONE">
<id name="id" type="java.lang.Long">
<column name="MS_ID" precision="16" scale="0" />
<generator class="native" />
</id>
省略很多配置信息.......
<many-to-one name="flowComb" class="com.bwol.pm.project.entity.FlowComb" fetch="select">
<column name="COMB_ID" precision="16" scale="0" />
</many-to-one>
</class>
问题分析
bug报错的原因是:Hibernate的session 关闭了,要从一个懒加载代理对象中获取数据就会报这个错。
我的程序中是通过hibernate获取到Milestone的代理对象,然后将其保存在HttpRequest的session中。在调用MilestoneDao里Hibernate session获取到的是的Milestone代理类对象,整个Session范围内,应用程序没有访问过Milestone对象,只是保存在了HttpRequest的session中。那么Milestone代理类的实例一直不会被初始化。事务是作用在MilestoneService上,导致其在获取Milestone调用之前获取Session、开启事务,这个方法结束之后提交事务、关闭session。session关闭后,在别的地方获取Milestone时是未初始化的Milestone代理类对象,未被初始化的代理类对象只有OID其他属性全为null,在通过Milestone获取其他的多对一数据时,必然会发生懒加载异常。
解决方式
首先感谢 博客园 阳台煮酒 博主提供的解决问题的博客 https://www.cnblogs.com/TTTTT/p/6682798.html 并且博主给出了3个解决方案,但是我都没有采用,我简单暴力的在通过 milestoneService调用getById的方式再次获取一次成功解决问题。代码的操作方式如下:
Milestone mileStone = this.getMilestoneBySession();
Long mileId = mileStone.getId();
mileStone = milestoneService.getById(mileId);
List<FlowFlow> flowList = mileStone.getFlowComb().getFlowList();