java 具有相同标识符值的不同对象已与会话关联:。合并和 saveOrUpdate 都不起作用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14751730/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
A different object with the same identifier value was already associated with the session:. neither merge nor saveOrUpdate works
提问by chris
I have a GUI where a list of teachers is shown. Two are selected by the user - they are going to be the form teachers of a new school class that gets created. The teacher - class relationship is n-m.
我有一个 GUI,其中显示了教师列表。用户选择了两个 - 他们将成为创建的新学校班级的形式教师。老师-班级关系是nm。
School class: (it inherits its id from its group)
学校类:(它从它的组继承它的id)
@Entity
@Table(name="school_classes")
@Cacheable(true)
public class SchoolClass extends Group{
@ManyToMany(cascade=CascadeType.ALL, mappedBy="classes", fetch=FetchType.EAGER)
private SortedSet<Teacher> teachers;
Teacher:
老师:
@Entity
@Table(name="teachers")
@Cacheable(true)
public class Teacher extends creator.models.school.Entity{
// name etc
@ManyToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
@JoinTable(name="class_teachers",
joinColumns = @JoinColumn(name="teacher_id", referencedColumnName="id"),
inverseJoinColumns = @JoinColumn(name="class_id", referencedColumnName="id"))
private SortedSet<SchoolClass> classes;
I try to create a new class like this:
我尝试创建一个这样的新类:
String className = request.getParameter("class_name");
String id1 = request.getParameter("class_teacher1");
String id2 = request.getParameter("class_teacher2");
Teacher t1 = DataRetrieveModule.getTeacher(id1);
Teacher t2 = DataRetrieveModule.getTeacher(id2);
Layout l = new Layout();
SchoolClass newClass = new SchoolClass(className);
newClass.setLayout(l);
newClass.addTeacher(t1);
t1.addClass(newClass);
newClass.addTeacher(t2);
t2.addClass(newClass);
DataInsertionModule.insert(newClass);
This statement DataRetrieveModule.getTeacher(id1)
opens a session, retrives the teacher by ID and closes it.
DataInsertionModule.insert(newClass)
also opens a session, calls session.saveOrUpdate(newClass)
. (I also tried session.merge(newClass)
)
此语句DataRetrieveModule.getTeacher(id1)
打开一个会话,通过 ID 检索教师并关闭它。
DataInsertionModule.insert(newClass)
还打开一个会话,调用 session.saveOrUpdate(newClass)
. (我也试过session.merge(newClass)
)
Retrieving a teacher:
找老师:
public static Teacher getTeacher(String id) {
Session session = null;
Teacher t = null;
try{
sessionFactory = MyFactory.getSessionFactory();
session = sessionFactory.openSession();
t = (Teacher) session.get(Teacher.class, Long.parseLong(id));
}
catch(Exception e) {
System.out.println("in DAO:");
e.printStackTrace();
if(session!=null)
session.close();
}
finally{
if(session!=null)
session.close();
}
return t;
}
Data insertion:
数据插入:
public static void insert(Object o) {
Session session = null;
try
{
sessionFactory = MyFactory.getSessionFactory();
session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
session.save(o);
tx.commit();
System.out.println("insertion done");
}
catch (Exception e)
{
System.out.println(e.getMessage());
e.printStackTrace();
}
finally
{
if(session!=null)
session.close();
}
}
But insertion never works. There is always an object with the same id that already exists.
但插入永远不起作用。总是有一个具有相同 id 的对象已经存在。
a different object with the same identifier value was already associated with the session: [creator.models.school.Teacher#3]
I searched on stackoverflow and have overridden my getHashCode and equals method in the class all my business objects inherit from:
我在 stackoverflow 上搜索并在类中覆盖了我的 getHashCode 和 equals 方法,我的所有业务对象都继承自:
@Override
public int compareTo(Entity o) {
if(this.id < o.getId())
return -1;
else if(this.id > o.getId())
return 1;
return this.getClass().getName().compareTo(o.getClass().getName());
}
@Override
public boolean equals(Object o) {
if(o instanceof Entity)
return this.compareTo((Entity)o)==0;
else return this.equals(o);
}
@Override
public int hashCode() {
char[] bla = this.getClass().getName().toCharArray();
int blue=0;
for(char c:bla)
blue = blue*10 + c;
return (int) (id+blue);
}
Furthermore I tried to change the CascadeType
of ManyToMany
to MERGE
(reverted again).
此外,我尝试将CascadeType
of更改ManyToMany
为MERGE
(再次还原)。
At the moment I merge the teacher objects after retrieving both of them with session.get(..), as retrieving takes a lot of data out of the DB. There are futher ..ToMany
relations. Therefore it probably might happen, that the call causes that both teachers are loaded.
目前,我在使用 session.get(..) 检索了教师对象后合并了它们,因为检索会从数据库中取出大量数据。还有进一步的 ..ToMany
关系。因此,可能会发生这种情况,调用会导致两个老师都被加载。
public static Object merge(Object o) {
Session session = null;
Object returnVal = null;
try
{
sessionFactory = MyFactory.getSessionFactory();
session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
returnVal = session.merge(o);
tx.commit();
}
catch (Exception e)
{
System.out.println(e.getMessage());
e.printStackTrace();
}
finally
{
if(session!=null)
session.close();
}
return returnVal;
}
.
.
Teacher t1 = DataRetrieveModule.getTeacher(id1);
Teacher t2 = DataRetrieveModule.getTeacher(id2);
t1= DataInsertionModule.merge(t1);
t2= DataInsertionModule.merge(t2);
Therefore I thought, that if I merge the one my get-method returned with the one that must have been loaded by the get call for the other teacher, it should work. (like here: http://www.stevideter.com/2008/12/07/saveorupdate-versus-merge-in-hibernate/) But it does not :(
因此,我想,如果我将我的 get 方法返回的那个与另一个老师的 get 调用必须加载的那个合并,它应该可以工作。(就像这里:http: //www.stevideter.com/2008/12/07/saveorupdate-versus-merge-in-hibernate/)但它没有:(
Is it probably because an object of the same superclass (Object or my Entity class) has the same ID?
是否可能是因为同一个超类(对象或我的实体类)的对象具有相同的 ID?
Please help me!
请帮我!
回答by Tobb
One potential situation that could lead to this error is when the id of teacher 1 and teacher 2 is the same. Since you close the session between each get they will be detached, and you would end up loading two different objects that both represent the same row in the database (they have the same primary key.) Then, when these are both going to be reattached to a session through a SchoolClass being saved, Hibernate will see two different objects both representing the same row in the database, and not know which one represent the correct state to persist to the database.
可能导致此错误的一种潜在情况是教师 1 和教师 2 的 ID 相同。由于您关闭了每个 get 之间的会话,它们将被分离,并且您最终会加载两个不同的对象,它们都代表数据库中的同一行(它们具有相同的主键。)然后,当它们都将被重新附加时对于通过 SchoolClass 保存的会话,Hibernate 将看到两个不同的对象,它们都代表数据库中的同一行,并且不知道哪个代表了要持久化到数据库的正确状态。
Don't know for sure if this is the case here, but you should run a debugger and check the state of the objects referenced by teacher1 and teacher2.
不确定这里是否是这种情况,但是您应该运行调试器并检查由teacher1 和teacher2 引用的对象的状态。