![](/img/trans.png)
[英]Caused by: org.hibernate.HibernateException: Found shared references to a collection
[英]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.