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);为什么会出现此异常的原因及直接解决方式目前尚不知道,待解决..

 

posted @ 2015-10-09 18:15  Tom1997  阅读(742)  评论(0编辑  收藏  举报