在刚接触hibernate时,不可避免要遇见这个问题:LazyInitiazationException---could not initialize proxy,the owning Session was closed
例子:一个班级可以有多个学生,一个学生有一个身份证。
.....//打开Session1,开启事务
Student stu = (Student)session1.get(Strudent.class," ") //" "内为学生主键,通过这个主键获得学生的实例
.....//提交事务,关闭Session1
System.out.println( stu.getNme() ) ; //获取学生姓名
System.out.println( stu.getTeam() ); //获取学生所在班级
System.out.println( stu.getTeam().getStudents.size() ); //获取学生所在班级的学生数量
出错原因:当取的学生对象后,由于采取的是延迟加载,hibernate只是生成一个班级代理对象(只是壳,没有数据)。出错的原因就是取的学生对象后,session关闭了,这时班级代理对象就成了孤儿,没有了数据来源(除非把班级对象重新纳入一个session范围才能用数据填充这个壳)。因此当你再想去获取班级里的学生(或者其他属性),就会出现这个例外。
纠正方法:把班级对象纳入另外一个Session中,使用 org.hibernate.Hibernate 这个类的 initialize()方法强制把班级代理这个壳填充数据(也可以看为将班级对象初始化)。但是调用这个方法时,还要做一件事情,就是将班级这个对象与这个Session重新关联。这是因为班级对象在第一个Session关闭后变成了脱管状态,在这个Session中无法初始化一个脱管状态对象。要重新关联就要用到session.update(),此方法作用除了更新对象外,还能把脱管对象和Session进行关联。
改正后代码:
.....//打开Session1,开启事务
Student stu = (Student)session1.get(Strudent.class," ") //" "内为学生主键,通过这个主键获得学生的实例
.....//提交事务,关闭Session1
.....//打开Session2,开启事务
session2.update( stu.getTeam() ); //把脱管的班级对象与Session2关联
Hibernate.initialize( stu.getTeam() ); //初始化班级对象
Hibernate.initialize( stu.getTeam().getStudents() ); //初始化班级所有的学生对象
System.out.println( stu.getNme() ) ; //获取学生姓名
System.out.println( stu.getTeam() ); //获取学生所在班级
System.out.println( stu.getTeam().getStudents.size() ); //获取学生所在班级的学生数量
从中获得:(从下往上看:4、3、2、1)
1.用Hibernate.initialize()初始化一个代理对象(获取代理对象Set里面的数据)
2.将一个脱管对象与Session相关联session.update()
3.脱管对象无法被初始化
4.一个事务提交后关闭Session后,剩余的对象就变为了脱管对象