1. ホーム
  2. java

[解決済み] PersistentObjectException: JPAとHibernateが投げるpersistに渡されたデタッチド・エンティティー

2022-01-28 01:41:34

質問

JPAパーシステッドオブジェクトモデルに多対一のリレーションシップがあります。 Account は、多くの Transactions . A Transaction は1つの Account .

以下はコードのスニペットです。

@Entity
public class Transaction {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @ManyToOne(cascade = {CascadeType.ALL},fetch= FetchType.EAGER)
    private Account fromAccount;
....

@Entity
public class Account {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    @OneToMany(cascade = {CascadeType.ALL},fetch= FetchType.EAGER, mappedBy = "fromAccount")
    private Set<Transaction> transactions;

を作成することができました。 Account オブジェクトを作成し、それにトランザクションを追加し、そして Account オブジェクトが正しく表示されます。しかし、トランザクションを作成すると 既に永続化された既存のアカウントを使って を作成し トランザクション という例外が発生します。

原因: org.hibernate.PersistentObjectException: 永続化するために渡された未知のエンティティ: com.paulsanwald.Account at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:141)

ということで Account トランザクションを含むトランザクションは含まれません。 Account . これは Account が付いていない可能性がありますが、このコードでも同じ例外が発生します。

if (account.getId()!=null) {
    account = entityManager.merge(account);
}
Transaction transaction = new Transaction(account,"other stuff");
 // the below fails with a "detached entity" message. why?
entityManager.persist(transaction);

を正しく保存するにはどうすればよいですか? Transaction に関連付けられ、既に永続化された Account オブジェクトを作成しますか?

解決方法は?

これは典型的な双方向性一貫性の問題です。この問題については このリンク と同様に このリンク

前の2つのリンクの記事にあるように、双方向の関係の両側でセッターを固定する必要があります。片方のセッターの例は、次のとおりです。 このリンク

Many側のセッターの例としては このリンク

セッターを修正したら、Entity のアクセス タイプを "Property"にすることを宣言します。アクセスタイプを "Property"と宣言するベストプラクティスは、メンバープロパティから対応するゲッターにすべての注釈を移動することです。注意点としては、エンティティクラス内で "Field" と "Property" のアクセスタイプを混在させないことで、JSR-317仕様で定義されていない動作となります。