教師のリストが表示されるGUIがあります。2人はユーザーによって選択されます-彼らは作成される新しい学校のクラスのフォーム教師になります。教師とクラスの関係はnmです。
学校のクラス:(グループから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;
先生:
@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;
私はこのような新しいクラスを作成しようとしています:
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);
このステートメントDataRetrieveModule.getTeacher(id1)
はセッションを開き、IDで教師を取得して閉じます。
DataInsertionModule.insert(newClass)
また、セッションを開き、を呼び出します session.saveOrUpdate(newClass)
。(私も試しましたsession.merge(newClass)
)
教師の取得:
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;
}
データ挿入:
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();
}
}
しかし、挿入は機能しません。すでに存在する同じIDのオブジェクトが常に存在します。
a different object with the same identifier value was already associated with the session: [creator.models.school.Teacher#3]
私は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);
}
CascadeType
さらに、のをに変更しようとしManyToMany
ましたMERGE
(再び元に戻しました)。
現時点では、両方をsession.get(..)で取得した後、教師オブジェクトをマージします。これは、取得するとDBから大量のデータが取得されるためです。さらに ..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);
したがって、get-methodが返したものを、他の教師のget呼び出しによってロードされたはずのメソッドとマージすると、機能するはずだと思いました。(ここのように:http://www.stevideter.com/2008/12/07/saveorupdate-versus-merge-in-hibernate/)しかし、そうではありません:(
同じスーパークラスのオブジェクト(Objectまたは私のEntityクラス)が同じIDを持っていることが原因である可能性がありますか?
私を助けてください!