org.hibernate.LazyInitializationException
1.org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.chen.vo.Teacher.students, no session or session was closed
异常描述:运行以下方法出现。注:持久类Teacher与Student呈多对多关联。
@Test//fail public void query2(){ List list = hibernateTemplate.find("from Teacher t where t.id=69"); if(list.size()>0){ Teacher t = (Teacher) list.get(0); Set<Student> ss = t.getStudents(); for (Student student : ss) { System.out.println(student); } } System.out.println(list); }
具体异常信息:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.chen.vo.Teacher.students, no session or session was closed
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:380)
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:372)
at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:365)
at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:108)
at org.hibernate.collection.PersistentSet.toString(PersistentSet.java:332)
at java.lang.String.valueOf(String.java:2854)
at java.io.PrintStream.println(PrintStream.java:821)
at com.chen.test.Many2ManyTest.query2(Many2ManyTest.java:248)
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:606)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:232)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:89)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:175)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
解决方法:修改2个持久类的配置文件,在set处加上 lazy="false" cascade="all",many-to-many处加上 lazy="false"
1.修改Teacher.hbm.xml
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.chen.vo.Teacher"> <id name="id"> <generator class="native" /> </id> <property name="name" /> <!-- 通过table项告诉hibernate中间表的名称 --> <set name="students" table="teacher_student" lazy="false" cascade="all"> <!-- 通过key属性告诉hibernate在中间表里面查询teacher_id值相应的teacher记录 --> <key column="teacher_id" /> <!-- 通过column项告诉hibernate对student表中查找student_id值相就的studnet记录 --> <many-to-many class="com.chen.vo.Student" column="student_id" lazy="false" /> </set> </class> </hibernate-mapping>
2.修改Student.hbm.xml
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.chen.vo.Student" > <id name="id" > <generator class="native" /> </id> <property name="name" /> <set name="teachers" table="teacher_student" lazy="false" cascade="all"> <key column="student_id" /> <many-to-many class="com.chen.vo.Teacher" column="teacher_id" lazy="false" /> </set> </class> </hibernate-mapping>
运行query2方法,正常!结果如下:(注:Student未显示老师原因在于在类Student中的toString方法中没有设置。)
Student [id=71, name=s1] Student [id=72, name=s2] [Teacher [id=69, name=t1, students=[Student [id=71, name=s1], Student [id=72, name=s2]]]]
小结:failed to lazily initialize a collection of role: com.chen.vo.Teacher.students这个异常信息说明异常出在懒加载上。
2.org.hibernate.LazyInitializationException: could not initialize proxy - no Session
异常描述:运行以下方法出现,注:执行这个方法是在已处理上面异常1的前提下,即执行query2正常,执行下面的query3却失败。
@Test//fail public void query3(){ Teacher t = hibernateTemplate.load(Teacher.class, 69); System.out.println(t); // System.out.println(t.getStudents()); }
具体异常信息:
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:132)
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:174)
at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:190)
at com.chen.vo.Teacher_$$_javassist_0.getStudents(Teacher_$$_javassist_0.java)
at com.chen.test.Many2ManyTest.query3(Many2ManyTest.java:255)
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:606)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:232)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:89)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:175)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
解决方法:
目前只有替换方法,1是将hibernateTemplate.load(Teacher.class, 69);这种查询换为query2中的hibernateTemplate.find("from Teacher t where t.id=69");或者直接获取Hibernate的原生session,如下所示:
public void query(int id){ Session s = null; Transaction tx = null; SessionFactory sessionFactory = hibernateTemplate.getSessionFactory(); s = sessionFactory.openSession(); tx = s.beginTransaction(); Teacher t = (Teacher) s.get(Teacher.class, id); System.out.println("students:"+t.getStudents()); System.out.println("students的个数:" + t.getStudents().size()); tx.commit(); s.close(); } @Test public void query(){ query(69); }
小结:hibernateTemplate.load(Teacher.class, 69);为什么会出现此异常的原因及直接解决方式目前尚不知道,待解决..