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


119

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();

この場合、クエリは次のように生成されます

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

そのため、persist()メソッドは挿入と更新を生成できます。

今と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

7
javadocは、それらが何をするのか、何が違うのかについて非常に明確です。読んで理解しましたか?
skaffman 2010


回答:


144

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

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

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

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

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

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

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


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

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

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

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

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

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

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


情報をありがとう。両方の定義の意味がわかります。しかし、問題はそれらの間の違いについてです。おそらく、persistvsの異なる動作ごとに状態のリストと2つのサブセクションを表示しmergeますか?
AlikElzin-kilaka

25

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

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

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


説明にソースを追加していただけますか?ありがとう。
AlikElzin-kilaka 2017年

@ AlikElzin-kilakaのような説明は、私が覚えているように、「Beginning Java EE 7」の本で見つけました。
クリスティアン2017年

12

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

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

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


1

最も重要な違いはこれです:

  • persistメソッドの場合、永続コンテキストで管理されるエンティティが永続コンテキストにすでに存在する場合、新しいエンティティは無視されます。(何も起こらなかった)

  • ただし、mergeメソッドの場合、永続コンテキストですでに管理されているエンティティは新しいエンティティ(更新済み)に置き換えられ、この更新されたエンティティのコピーが返されます。(永続コンテキストで変更を反映したい場合は、今後、この返されたエンティティに変更を加える必要があります)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.