11

と の 2 つのエンティティがAccountありAccountRoleます。

public class Account {
   private AccountRole accountRole;

   @ManyToOne(cascade = CascadeType.PERSIST, fetch = FetchType.EAGER)
   public AccountRole getAccountRole() {
      return accountRole;
   }

.

public class AccountRole {
    private Collection<Account> accounts = new ArrayList<Account>();

    @OneToMany(mappedBy = "accountRole", fetch = FetchType.EAGER)
    public Collection<Account> getAccounts() {
         return accounts;
    }

問題は、データベースから accountRole を取得し、自分のAccount. この時点で、アカウントを作成したばかりで、ロールは既に db に存在します。

AccountRole role = accountService.getRoleFromDatabase(AccountRoles.ROLE_USER);
account.setAccountRole(role);

//setting both ways, as suggested
public void setAccountRole(AccountRole accountRole) {
    accountRole.addAccount(this);
    this.accountRole = accountRole;
}

entityManager.persist(account); // finally in my DAO

私はこれを読みました: JPA/Hibernate: detached entity passed to persist そして、私が理解したことは、エンティティの値を両方向から設定する必要があるため、セッターで行っていることです。

それでもエラーが発生します。

 org.hibernate.PersistentObjectException: detached entity passed to persist: foo.bar.pojo.AccountRole
4

3 に答える 3

18

交換するだけ

entityManager.persist(account);

と:

entityManager.merge(account);

マージ カスケードを許可します。

@ManyToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE }, fetch = FetchType.EAGER)
public AccountRole getAccountRole() {
    return accountRole;
}

マージはこれを行うため:

エンティティが新しい場合は、persist() と同じです。ただし、エンティティが既に存在する場合は、エンティティが更新されます。

于 2012-12-12T10:16:35.340 に答える
3

処理中にトランザクションを離れたように見えるため、accountRoleが切り離されているか、他の理由で既に切り離されています。

呼び出すentityManager.merge(accountRole)前に呼び出してentityManager.persist(account)修正する必要があります。

accountRole編集: 残念ながら、 DB に既に存在するかどうかわからない場合は、クエリを実行して確認する必要があります。存在する場合はマージし、存在しない場合は永続化します。確かに面倒ですが、これ以上の回避策はまだ見たことがありません。

EDIT2: メソッドに渡すエンティティmergeは切り離されたままになります。マネージド エンティティは によって返されるため、最初にマージしてから、 の参照を の戻り値にmerge設定する必要があります。accountmerge

于 2012-12-12T09:12:14.257 に答える
0

データ化されたエンティティを永続化するために渡すことはできません。方法はありません。しかし、その必要はありません。

(すでに永続化されている)とはAccount独立して永続化したい。AccountRoleこれを実現するには、子エンティティからカスケードを削除する@ManyToOneだけです(Accountこの場合)。

public class Account {
    private AccountRole accountRole;

    @ManyToOne // no cascading here!
    public AccountRole getAccountRole() {
        return accountRole;
    }

ここで私の説明を参照してください。理由: https://stackoverflow.com/a/54271569/522578

于 2019-01-19T22:28:49.130 に答える