EclipseLink が Persistence プロバイダーである JPA プログラムがあります。ユーザー エンティティをマージし、その ID を変更して、同じユーザー インスタンスを再度マージしようとすると、エラーがスローされます。コードを書き直して、問題を最も簡単な方法で説明します。
User user = userManager.find(1);
userManager.merge(user);
System.out.println("User is managed? "+userManager.contains(user);
user.setId(2);
userManager.merge(user);
上記のコードは、トランザクション コンテキストではありません。userManager は、EntityManager が注入されたステートレス セッション Bean です。実行すると、コンソールに次のように出力されます。
User is managed? false
Exception [EclipseLink-7251] (Eclipse Persistence Services - 2.1.3.v20110304-r9073): org.eclipse.persistence.exceptions.ValidationException
Exception Description: The attribute [id] of class [demo.model.User] is mapped to a primary key column in the database. Updates are not allowed.
例外は、2 回目の merge() 呼び出しで発生します。
新しいユーザーを作成し、その ID を設定してマージすると、次のように機能します。
User user = userManager.find(1);
userManager.merge(user);
System.out.println("User is managed? "+userManager.contains(user);
User newUser = new User();
newUser.setId(2);
userManager.merge(newUser);
では、最初のシナリオと 2 番目のシナリオの違いは何ですか? JPA の仕様によると、エンティティがデタッチされた状態にある限り、マージは成功するはずですよね? (ID=2のエンティティが存在すると仮定)
ユーザー・エンティティーが以前にマージされたという事実に EclipseLink プロバイダーが悩まされているように見えるのはなぜですか?
更新: EclipseLink のバグのようです。持続性プロバイダーを EclipseLink から Hibernate に置き換えました。
私が変える
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
に
<provider>org.hibernate.ejb.HibernatePersistence</provider>
エラーはスローされていません。