JPA EntityManager。なぜ、merge()ではなくpersist()を使用するのですか?
EntityManager.merge()
は,新しいオブジェクトを挿入したり,既存のオブジェクトを更新したりすることができます。
なぜpersist()
(新しいオブジェクトを作成することしかできない)を使いたいのでしょうか?
920
3
EntityManager.merge()
は,新しいオブジェクトを挿入したり,既存のオブジェクトを更新したりすることができます。
なぜpersist()
(新しいオブジェクトを作成することしかできない)を使いたいのでしょうか?
どちらの方法でもPersistenceContextにエンティティを追加しますが、違いはその後のエンティティの処理にあります。
Persistは、エンティティのインスタンスを取得し、コンテキストに追加し、そのインスタンスを管理します(つまり、将来のエンティティの更新が追跡されます)。
Merge は、エンティティの新しいインスタンスを作成し、渡されたエンティティから状態をコピーし、新しいコピーを管理するようにします。あなたが渡したインスタンスは管理されません(あなたが行った変更はトランザクションの一部ではありません-あなたが再度 merge を呼び出さない限り)。
コード例が参考になるかもしれません。
シナリオ1とシナリオ3はほぼ同等ですが、シナリオ2を使いたい場面もあるでしょう。
em.merge
を使用すると、JPAが生成するフィールドがない場合でも、
INSERTごとに
SELECT文が表示されることに気づきました(主キーフィールドは自分で設定したUUIDでした)。 そこで、
em.persist(myEntityObject)に切り替えたところ、
INSERT`文だけが表示されるようになりました。セッション中のレイジーロードされたコレクションにアクセスしようとしていたため、エンティティでレイジーロードの例外が発生していました。
私は別のリクエストで、セッションからエンティティを取得し、その後jspページでコレクションにアクセスしようとしましたが、これは問題がありました。
この問題を解決するために、コントローラで同じエンティティを更新し、それをjspに渡しました。ただし、セッションで保存しなおしたときには、
SessionScope
からもアクセスできるようになり、LazyLoadingException
を投げることはないと想像していますが、例2の修正です。私の場合は以下のようになりました。