LazyInitializationException: 在Hibernate中从与原始会话不同的会话中加载延迟属性

huangapple go评论79阅读模式
英文:

LazyInitializationException: load lazy attribute from a session different from the original one in Hibernate

问题

我是初学者正在学习 Hibernate并尝试了解急加载和懒加载

我知道如果 Hibernate 会话已关闭然后我尝试检索懒加载数据那么 Hibernate 将抛出异常

现在我尝试在第一个会话中加载主实体Instructor),然后在一个***新的独立会话***中加载从属实体Course):

**主类测试类**

```java
public class EagerLazyDemo {
    public static void main(String[] args) {

        SessionFactory factory = new Configuration().configure("hibernate.cfg.xml")
                .addAnnotatedClass(Instructor.class)
                .addAnnotatedClass(InstructorDetail.class)
                .addAnnotatedClass(Course.class)
                .buildSessionFactory();

        Session session = factory.getCurrentSession();

        // 开始事务
        session.beginTransaction();

        // 从数据库获取讲师信息
        Instructor theInstructor = session.get(Instructor.class, 1);

        // 提交事务
        session.getTransaction().commit();

        session.close();

        //------

        // 新会话
        session = factory.getCurrentSession();
        session.beginTransaction();

        // 获取并显示讲师的课程
        List<Course> courses = theInstructor.getCourses();
        printCourses(courses);

        session.getTransaction().commit();
        session.close();

    }

    private static void printCourses(List<Course> courses) {
        for (Course c : courses) {
            System.out.println(c);
        }
    }
}

但是 Hibernate 抛出了以下异常:

错误:

Exception in thread "main" org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.mehdisarf.hibernate.demo.entity.Instructor.courses, could not initialize proxy - no Session
    at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:606)
    at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:218)
    at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:585)
    at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:149)
    at org.hibernate.collection.internal.PersistentBag.iterator(PersistentBag.java:387)
    at com.mehdisarf.hibernate.demo.EagerLazyDemo.printCourses(EagerLazyDemo.java:55)
    at com.mehdisarf.hibernate.demo.EagerLazyDemo.main(EagerLazyDemo.java:42)

它表示:

> 无法初始化代理 - 没有会话

尽管我已经为加载从属实体创建了一个会话

以下是我的实体类:

讲师类(主实体)

@Entity
@Table(name = "instructor")
public class Instructor {

    // ... (省略其他代码)

    @OneToMany(fetch = FetchType.LAZY,
            mappedBy = "instructor",
            cascade = {CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH})
    private List<Course> courses;

    // ... (省略其他代码)
}

课程类(从属实体)

@Entity
@Table(name = "course")
public class Course {

    // ... (省略其他代码)

    @ManyToOne(cascade = {CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH})
    @JoinColumn(name = "instructor_id")
    private Instructor instructor;

    // ... (省略其他代码)
}

<details>
<summary>英文:</summary>
I&#39;m beginner at hibernate and try to learn eager and lazy loading
I know that if the hibernate session is closed and then I try to retrieve lazy data, then Hibernate will throw an exception. 
Now, I&#39;ve tried to load main entity(Instructor) in first session and then load dependent entity(Course) in a ***new separate session***: 
**Main Class(Test Class)**
public class EagerLazyDemo {
public static void main(String[] args) {
SessionFactory factory = new Configuration().configure(&quot;hibernate.cfg.xml&quot;)
.addAnnotatedClass(Instructor.class)
.addAnnotatedClass(InstructorDetail.class)
.addAnnotatedClass(Course.class)
.buildSessionFactory();
Session session = factory.getCurrentSession();
// Begin A Transaction
session.beginTransaction();
// Get The Instructor From DB
Instructor theInstructor = session.get(Instructor.class, 1);
// Commit Transaction
session.getTransaction().commit();
session.close();
//------
//new session
session = factory.getCurrentSession();
session.beginTransaction();
//Get And Display Courses For The Instructor
List&lt;Course&gt; courses = theInstructor.getCourses();
printCourses(courses);
session.getTransaction().commit();
session.close();
}
private static void printCourses(List&lt;Course&gt; courses) {
for (Course c : courses) {
System.out.println(c);
}
}
}
but hibernate throw this exception:  
**Error:**
Exception in thread &quot;main&quot; org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.mehdisarf.hibernate.demo.entity.Instructor.courses, could not initialize proxy - no Session
at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:606)
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:218)
at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:585)
at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:149)
at org.hibernate.collection.internal.PersistentBag.iterator(PersistentBag.java:387)
at com.mehdisarf.hibernate.demo.EagerLazyDemo.printCourses(EagerLazyDemo.java:55)
at com.mehdisarf.hibernate.demo.EagerLazyDemo.main(EagerLazyDemo.java:42)
**it says:**
&gt; could not initialize proxy - no Session
Although I have a session for loading dependent entity
**These Are My Entity Classes:**
**Instructor Class (main entity)**
@Entity
@Table(name = &quot;instructor&quot;)
public class Instructor {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = &quot;id&quot;)
private int id;
@Column(name = &quot;first_name&quot;)
private String firstName;
@Column(name = &quot;last_name&quot;)
private String lastName;
@Column(name = &quot;email&quot;)
private String email;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = &quot;instructor_detail_id&quot;)
private InstructorDetail instructorDetail;
@OneToMany(fetch = FetchType.LAZY,
mappedBy = &quot;instructor&quot;,
cascade = {CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH})
private List&lt;Course&gt; courses;
public Instructor() {
}
public Instructor(String firstName, String lastName, String email) {
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
}
public void addCourse(Course theCourse) {
if (courses == null) {
courses = new ArrayList&lt;&gt;();
}
this.courses.add(theCourse);
theCourse.setInstructor(this);
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public InstructorDetail getInstructorDetail() {
return instructorDetail;
}
public void setInstructorDetail(InstructorDetail instructorDetail) {
this.instructorDetail = instructorDetail;
}
public List&lt;Course&gt; getCourses() {
return courses;
}
public void setCourses(List&lt;Course&gt; courses) {
this.courses = courses;
}
@Override
public String toString() {
return id + &quot;&quot; + firstName + &quot;&quot; + lastName + &quot;&quot; + email + &quot;  (Detail:&quot; + instructorDetail+&quot;)&quot;;
}
}
**Course Class (dependent entity)**
@Entity
@Table(name = &quot;course&quot;)
public class Course {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = &quot;id&quot;)
private int id;
@Column(name = &quot;title&quot;)
private String title;
@ManyToOne(cascade = {CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH})
@JoinColumn(name = &quot;instructor_id&quot;)
private Instructor instructor;
public Course() {
}
public Course(String title) {
this.title = title;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Instructor getInstructor() {
return instructor;
}
public void setInstructor(Instructor instructor) {
this.instructor = instructor;
}
@Override
public String toString() {
return id + &quot;|&quot; + title + &quot;|&quot;;
}
}
</details>
# 答案1
**得分**: 2
你的对象theInstructor仍然与之前的会话关联。为了检索你的对象,在打开新会话后,你需要进行另一个调用:
theInstructor = session.get(Instructor.class, 1);
<details>
<summary>英文:</summary>
Your object theInstructor is still linked to the former session. In order to retrieve your object you have to make another call after opening the new session :
theInstructor = session.get(Instructor.class, 1);
</details>
# 答案2
**得分**: 1
"theInstructor"在进行"theInstructor.getCourses()"调用时,并未连接到任何会话,这导致了异常。
当对象通过get方法返回时,它处于持久状态。
> 任何由get()或load()方法返回的实例都是持久的。[会话文档][1]
当会话关闭时,"theInstructor"对象进入脱离状态。
> 脱离状态 - 脱离的实例是指已经持久化,但其会话已关闭的对象。[Hibernate对象状态文档][2]
调用`session = factory.getCurrentSession();`返回新的会话对象,但"theInstructor"对象并未连接到新会话。因此,尝试惰性加载课程时会失败。
[1]: https://docs.jboss.org/hibernate/orm/3.5/api/org/hibernate/Session.html#get(java.lang.Class,%20java.io.Serializable)
[2]: https://docs.jboss.org/hibernate/core/3.5/reference/en/html/objectstate.html
<details>
<summary>英文:</summary>
&quot;theInstructor&quot; is not attached to any session while &quot;theInstructor.getCourses()&quot; call is made, this results in exception.
When object is returned by the get method it is in the Persistent state.
&gt; Any instance returned by a get() or load() method is persistent
[Session Documentation][1]
When session is closed &quot;theInstructor&quot; object goes into the Detached state.
&gt; Detached - a detached instance is an object that has been persistent, but its Session has been closed. [Hibernate object states documentation][2]
Call made to `session = factory.getCurrentSession();` returns new session object, but `theInstructor` object is not attached to the new session. Hence an attempt to lazily load the courses fails.
[1]: https://docs.jboss.org/hibernate/orm/3.5/api/org/hibernate/Session.html#get(java.lang.Class,%20java.io.Serializable)
[2]: https://docs.jboss.org/hibernate/core/3.5/reference/en/html/objectstate.html
</details>

huangapple
  • 本文由 发表于 2020年5月5日 05:20:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/61601826.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定