簡體   English   中英

Hibernate在entitymanager.flush()上拋出“ org.hibernate.HibernateException:找到相同集合的兩個表示形式”

[英]Hibernate throws “org.hibernate.HibernateException: Found two representations of same collection” on entitymanager.flush()

我目前正在使用Hibernate進行一個中等規模的Java項目,遇到了一個罕見的但相當持久的錯誤。 情況如下:我有一個Student實體,該實體與Education實體具有雙向多對多關系(在數據庫上實現為聯接表),而Admin實體是Student的子類。 我的代碼允許通過從數據庫中刪除學生,基於學生創建一個新的管理員並持久保留該管理員來將“學生”“升級”為管理員。 但是,無論何時發生這種情況,Hibernate都會在EntityManager.flush()上引發以下錯誤:

org.hibernate.HibernateException: Found two representations of same collection: domain.Student.enrolledEducations

您可以在下面找到相關代碼:

教育班

@Entity
public class Education {

...

@ManyToMany
@JoinColumn(name = "education_id")
private Set<Course> courses = new HashSet<>();

學生班

@Entity
public class Student {

....

@ManyToMany
@JoinColumn(name = "student_id")
private Set<Education> enrolledEducations = new HashSet<>();

管理員班

@Entity
public class Admin extends Student {

...

public Admin(Student student) {
    this.setId(student.getId());
    this.setFirstName(student.getFirstName());
    this.setLastName(student.getLastName());
    this.setEmail(student.getEmail());
    this.setSalt(student.getSalt());
    this.setSuperAdmin(false);
    this.setEnrolledEducations(student.getEnrolledEducations());
    this.setSessions(student.getSessions());
    this.setManagedEducations(new HashSet<Education>());
}

數據庫方法

public Admin upgrade(Person person) {
    Admin admin;
    if (person instanceof Student){
        removeStudent((Student) person);
        admin = new Admin((Student) person);
    }
    else{
        removePerson(person);
        admin = new Admin(person);

    }
    addAdmin(admin); //exception happens here

    return admin;
}

public void addAdmin(Admin admin) {
    manager.getTransaction().begin();

    if(manager.contains(admin)){
        manager.merge(admin);
    }
    else{
        manager.persist(admin);
    }

    manager.flush(); //exception happens here
    manager.getTransaction().commit();
}

測試方法

@Test
public void getEducationsForAdmin_and_upgrade_to_admin_work_correctly(){

    educationSetup();

    Admin admin1 = facade.upgrade(student1); //exception happens here
    Admin admin2 = facade.upgrade(student2);

    admin1.addNewEducation(education1);
    admin1.addNewEducation(education2);
    admin2.addNewEducation(education1);

    facade.updateAdmin(admin1);
    facade.updateAdmin(admin2);

    Set<Education> educations1 = new HashSet<>(facade.getEducationsForStudent(admin1));
    Set<Education> educations2 = new HashSet<>(facade.getEducationsForStudent(admin2));

    assertTrue("admin 1 does not have exactly 1 education", educations1.size()==1);
    assertTrue("admin 2 does not have exactly 2 educations", educations2.size()==2);
    assertTrue("admin 1 does not have the IT education",educations1.contains(education1));
    assertTrue("admin 2 does not have the IT education",educations2.contains(education1));
    assertTrue("admin 2 does not have the M education",educations2.contains(education2));
}

似乎您有一個問題,即Admin和Student具有相同的標識符。

由於Admin是通過調用新函數創建的,因此它不是處於持久狀態,因此代碼

manager.contains(admin)

將始終返回false,因此它將始終轉到manager.persist語句。

由於Admin是具有相同標識符的其他對象,因此您將獲得異常

找到相同集合的兩個表示

您需要做的就是添加

manager.delete(person)

在你的

removePerson

功能。 它應該解決這個問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM