5

インメモリ Hibernate エンティティの現在の値をデータベースの値と比較したい:

HibernateSession sess = HibernateSessionFactory.getSession();
MyEntity newEntity = (MyEntity)sess.load(MyEntity.class, id);
newEntity.setProperty("new value");
MyEntity oldEntity = (MyEntity)sess.load(MyEntity.class, id);
// CODEBLOCK#1 evaluate differences between newEntity and oldEntity
sess.update(newEntity);    

CODEBLOCK#1では、そのnewEntity.getProperty()="new value"ANDを取得しますoldEntity.getProperty()="new value"(もちろん、期待していoldEntity.getProperty()="old value"ましたが)。実際、2 つのオブジェクトはメモリ内でまったく同じです。

いじって、それを取り除くようHibernateSessionFactory.getSession().evict(newEntity)に設定しようとしました(比較のためだけに必要です):oldEntity=null

HibernateSession sess = HibernateSessionFactory.getSession();
MyEntity newEntity = (MyEntity)sess.load(MyEntity.class, id);
newEntity.setProperty("new value");
HibernateSessionFactory.getSession().evict(newEntity);
MyEntity oldEntity = (MyEntity)sess.load(MyEntity.class, id);
// CODEBLOCK#1 evaluate differences between newEntity and oldEntity
oldEntity = null;
sess.update(newEntity);

そして今、2つのエンティティは別個のものですが、もちろん私は恐ろしいorg.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session.

何か案が?

EDIT:ダブルセッション戦略を試しました。HibernateSessionFactoryセッションのマップを実装するように変更した後...

Session session1 = HibernateSessionFactory.getSession(SessionKeys.DEFAULT);
Session session2 = HibernateSessionFactory.getSession(SessionKeys.ALTERNATE);
Entity newEntity = (Entity)entity;
newEntity.setNote("edited note");
Entity oldEntity = (Entity)session1.load(Entity.class, id);

System.out.println("NEW:" + newEntity.getNote());
System.out.println("OLD: " + oldEntity.getNote()); // HANGS HERE!!!

HibernateSessionFactory.closeSession(SessionKeys.ALTERNATE);

oldEntity ノートを印刷しようとしているときに、単体テストがハングします... :-(

4

2 に答える 2

8

2 つの簡単なオプションが思い浮かびます。

  1. newEntity を保存する前に oldEntity を削除する
  2. oldEntity で session.merge() を使用して、セッション キャッシュ内のバージョン (newEntity) を元の (oldEntity) に置き換えます。

EDIT : 少し詳しく説明すると、ここでの問題は、Hibernate が永続コンテキストを保持していることです。これは、各セッションの一部として監視されているオブジェクトです。コンテキストにアタッチされたオブジェクトがある場合、デタッチされたオブジェクト (コンテキストにないオブジェクト) に対して update() を実行することはできません。これはうまくいくはずです:

HibernateSession sess = ...;
MyEntity oldEntity = (MyEntity) sess.load(...);
sess.evict(oldEntity); // old is now not in the session's persistence context
MyEntity newEntity = (MyEntity) sess.load(...); // new is the only one in the context now
newEntity.setProperty("new value");
// Evaluate differences
sess.update(newEntity); // saving the one that's in the context anyway = fine

これもそうすべきです:

HibernateSession sess = ...;
MyEntity newEntity = (MyEntity) sess.load(...);
newEntity.setProperty("new value");
sess.evict(newEntity); // otherwise load() will return the same object again from the context
MyEntity oldEntity = (MyEntity) sess.load(...); // fresh copy into the context
sess.merge(newEntity); // replaces old in the context with this one
于 2008-10-09T09:42:23.967 に答える
0

session.isDirty() の使用はどうですか? JavaDoc によると、このメソッドは「このセッションをフラッシュした場合、SQL が実行されるか?」という質問に答えます。もちろん、これは新しいクリーンなセッションを開始する場合にのみ機能します。別のオプション - 2 つの異なるセッションを使用するだけです。

于 2008-10-08T17:06:13.900 に答える