スケのブログ

Java, Java EE, OpenAMなどの情報を記述していきます。

Stackoverflowの「JPA EntityManager: Why use persist() over merge()?」を翻訳

質問

EntityManager.merge()によって、新規オブジェクトを挿入し、存在している場合はそれを更新することができます。
何故、persist()を使用しないのでしょうか?(このメソッドは新規オブジェクトを生成するだけなのでしょうか)

回答

どちらもエンティティをPersistenceContextに追加する方法です。違いは追加後にエンティティに行うことです。

persist()によってエンティティインスタンスを取得し、PersistenceContextにエンティティを追加し、インスタンスのマージを行います。(すなわち、エンティティへの更新は後に行われます。(?))

merge()によってエンティティの新規インスタンスを生成します。もとであるエンティティから状態がコピーされ、コピーされたエンティティが管理される様になります。引数に渡したインスタンスは管理されません。(再びマージを行わないかぎり、あなたの変更はトランザクションの一部とみなされません。)

以下のコード例が理解する手助けになるでしょう。

MyEntity e = new MyEntity();

// シナリオ1
// トランザクション開始
em.persist(e); 
e.setSomeField(someValue); 
// トランザクション終了。someField列はDBで更新されます。

// シナリオ2
// トランザクション開始
e = new MyEntity();
em.merge(e);
e.setSomeField(anotherValue); 
// トランザクション終了。someField列は更新されません。
// (マージを行った後に変更を行っています。)

// シナリオ3
// トランザクション開始
e = new MyEntity();
MyEntity e2 = em.merge(e);
e2.setSomeField(anotherValue); 
// トランザクション終了。someField列はDBで更新されます。
// (変更はe2に対して行われます。eに対してではありません。)

シナリオ1と3はほぼ同じです。シナリオ2のような使い方をしたいということもあるかもしれません。