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

  • 相关阅读:
    【bzoj4596】[Shoi2016]黑暗前的幻想乡 容斥原理+矩阵树定理
    【bzoj4832】[Lydsy1704月赛]抵制克苏恩 期望dp
    【bzoj3796】Mushroom追妹纸 hash/sa+kmp+二分
    【bzoj3309】DZY Loves Math 莫比乌斯反演+线性筛
    【bzoj2813】 奇妙的Fibonacci数列 线性筛
    面向对象实现简单的学生课程选择
    小案例--面向对象中实现分页
    初识面向对象四(装饰器/反射)
    python小技巧--控制台输出带颜色的文字方法
    初识面向对象三(经典类/多态/鸭子类型/初识封装)
  • 原文地址:https://www.cnblogs.com/wql025/p/4864747.html
Copyright © 2011-2022 走看看