Note that there are some explanatory texts on larger screens.

plurals
  1. POA different object with the same identifier value was already associated with the session:. neither merge nor saveOrUpdate works
    primarykey
    data
    text
    <p>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.</p> <p>School class: (it inherits its id from its group)</p> <pre><code>@Entity @Table(name="school_classes") @Cacheable(true) public class SchoolClass extends Group{ @ManyToMany(cascade=CascadeType.ALL, mappedBy="classes", fetch=FetchType.EAGER) private SortedSet&lt;Teacher&gt; teachers; </code></pre> <p>Teacher:</p> <pre><code> @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&lt;SchoolClass&gt; classes; </code></pre> <p>I try to create a new class like this:</p> <pre><code>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); </code></pre> <p>This statement <code>DataRetrieveModule.getTeacher(id1)</code> opens a session, retrives the teacher by ID and closes it. <code>DataInsertionModule.insert(newClass)</code> also opens a session, calls <code>session.saveOrUpdate(newClass)</code>. (I also tried <code>session.merge(newClass)</code>)</p> <p>Retrieving a teacher:</p> <pre><code>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; } </code></pre> <p>Data insertion:</p> <pre><code>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(); } } </code></pre> <p>But insertion never works. There is always an object with the same id that already exists.</p> <pre><code>a different object with the same identifier value was already associated with the session: [creator.models.school.Teacher#3] </code></pre> <p>I searched on stackoverflow and have overridden my getHashCode and equals method in the class all my business objects inherit from:</p> <pre><code>@Override public int compareTo(Entity o) { if(this.id &lt; o.getId()) return -1; else if(this.id &gt; 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); } </code></pre> <p>Furthermore I tried to change the <code>CascadeType</code> of <code>ManyToMany</code> to <code>MERGE</code> (reverted again).</p> <p>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 <code>..ToMany</code> relations. Therefore it probably might happen, that the call causes that both teachers are loaded. </p> <pre><code>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; } </code></pre> <p>.</p> <pre><code>Teacher t1 = DataRetrieveModule.getTeacher(id1); Teacher t2 = DataRetrieveModule.getTeacher(id2); t1= DataInsertionModule.merge(t1); t2= DataInsertionModule.merge(t2); </code></pre> <p>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: <a href="http://www.stevideter.com/2008/12/07/saveorupdate-versus-merge-in-hibernate/" rel="nofollow">http://www.stevideter.com/2008/12/07/saveorupdate-versus-merge-in-hibernate/</a>) But it does not :(</p> <p>Is it probably because an object of the same superclass (Object or my Entity class) has the same ID? </p> <p>Please help me! </p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload