web-dev-qa-db-ja.com

JPAとHibernateのpersist()とmerge()の違いは何ですか?

Hibernateのpersist()とmerge()の違いは何ですか?

persist()は、UPDATEおよびINSERTクエリを作成できます。例:

SessionFactory sef = cfg.buildSessionFactory();
Session session = sef.openSession();
A a=new A();
session.persist(a);
a.setName("Mario");
session.flush();

この場合queryは次のように生成されます:

Hibernate: insert into A (NAME, ID) values (?, ?)
Hibernate: update A set NAME=? where ID=?

したがって、persist()メソッドはgenerate挿入と更新を実行できます。

merge()で:

SessionFactory sef = cfg.buildSessionFactory();
Session session = sef.openSession();
Singer singer = new Singer();
singer.setName("Luciano Pavarotti");
session.merge(singer);
session.flush();

これは私がデータベースで見るものです:

SINGER_ID   SINGER_NAME
1           Ricky Martin
2           Madonna
3           Elvis Presley
4           Luciano Pavarotti

merge()を使用してレコードを更新します

SessionFactory sef = cfg.buildSessionFactory();
Session session = sef.openSession();
Singer singer = new Singer();
singer.setId(2);
singer.setName("Luciano Pavarotti");
session.merge(singer);
session.flush();

これは私がデータベースで見るものです:

SINGER_ID   SINGER_NAME
1           Ricky Martin
2           Luciano Pavarotti
3           Elvis Presley
115
Jimit Tank

JPA仕様 には、javadocよりも優れた、これらの操作のセマンティクスの非常に正確な説明が含まれています。

エンティティXに適用されるpersist操作のセマンティクスは次のとおりです。

  • Xが新しいエンティティである場合、管理されます。エンティティXは、トランザクションのコミット時またはその前、またはフラッシュ操作の結果としてデータベースに入力されます。

  • Xが既存の管理対象エンティティである場合、永続化操作では無視されます。ただし、Xからこれらの他のエンティティへの関係にcascade=PERSISTまたはcascade=ALL注釈要素の値で注釈が付けられているか、同等のXML記述子要素で指定されている場合、永続操作はXによって参照されるエンティティにカスケードされます。

  • Xが削除されたエンティティである場合、管理されます。

  • Xが切り離されたオブジェクトの場合、永続操作が呼び出されたときにEntityExistsExceptionがスローされるか、フラッシュまたはコミット時にEntityExistsExceptionまたは別のPersistenceExceptionがスローされます。

  • Xからの関係によって参照されるすべてのエンティティYについて、Yへの関係にカスケード要素値cascade=PERSISTまたはcascade=ALLの注釈が付けられている場合、永続化操作がYに適用されます。


エンティティXに適用されるmerge操作のセマンティクスは次のとおりです。

  • Xが切り離されたエンティティである場合、Xの状態は、同じIDの既存の管理エンティティインスタンスX 'にコピーされるか、Xの新しい管理コピーX'が作成されます。

  • Xが新しいエンティティインスタンスの場合、新しい管理エンティティインスタンスX 'が作成され、Xの状態が新しい管理エンティティインスタンスX'にコピーされます。

  • Xが削除されたエンティティインスタンスである場合、マージ操作によってIllegalArgumentExceptionがスローされます(またはトランザクションのコミットが失敗します)。

  • Xが管理対象エンティティである場合、マージ操作では無視されますが、これらの関係にカスケード要素値cascade=MERGEまたはcascade=ALLアノテーションが付けられている場合、マージ操作はXの関係によって参照されるエンティティにカスケードされます。

  • カスケード要素値cascade=MERGEまたはcascade=ALLを持つXからのリレーションシップによって参照されるすべてのエンティティYについて、Yは再帰的にY 'としてマージされます。 Xによって参照されるこのようなすべてのYに対して、X 'はY'を参照するように設定されます。 (Xが管理されている場合、XはX 'と同じオブジェクトであることに注意してください。)

  • XがX 'にマージされたエンティティで、cascade=MERGEまたはcascade=ALLが指定されていない別のエンティティYへの参照がある場合、X'からの同じ関連付けのナビゲーションは、同じ永続IDを持つ管理対象オブジェクトY 'への参照を生成しますY.

142
axtavt

これはJPAから来ています。非常に簡単な方法で:

persist(entity)は、まったく新しいエンティティと共に使用して、それらをDBに追加する必要があります(エンティティがすでにDBに存在する場合、EntityExistsExceptionがスローされます)。

エンティティが切り離されて変更された場合、エンティティを永続コンテキストに戻すには、merge(entity)を使用する必要があります。

22
Krystian

Persistは新しいエンティティでのみ呼び出す必要がありますが、マージは分離されたエンティティを再アタッチすることを目的としています。

割り当てられたジェネレータを使用している場合、 persistの代わりにmergeを使用すると、冗長なSQLステートメントが発生する可能性があります 、したがってパフォーマンスに影響します。

また、管理対象エンティティはHibernateによって自動的に管理され、その状態は ダーティチェックメカニズム によってデータベースレコードと同期されるため、 管理対象エンティティのマージの呼び出し も誤りです。 永続コンテキストのフラッシュ

11
Vlad Mihalcea

最も重要な違いはこれです:persistメソッドの場合、永続コンテキストで管理されるエンティティが永続コンテキストに既に存在する場合、新しいエンティティは無視されます。 (何も起こらない)しかし、マージメソッドの場合、永続コンテキストで既に管理されているエンティティは新しいエンティティに置き換えられ(更新)、この更新されたエンティティのコピーが返されます。 (今後、永続コンテキストに変更を反映したい場合は、返されたエンティティに変更を加える必要があります)

1
Od Chan