Account
とAccountRole
の2つのエンティティがあります。
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
を永続化しようとすると問題が発生します。 この時点で、アカウントを作成したばかりで、役割はすでにデータベースに存在します。
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:永続化するために渡された切り離されたエンティティそして私が理解したことは、私がしていることをするために、両方向からエンティティ値を設定する必要があります私のセッターで。
まだエラーが発生しています。
org.hibernate.PersistentObjectException: detached entity passed to persist: foo.bar.pojo.AccountRole
交換するだけです
entityManager.persist(account);
と:
entityManager.merge(account);
そして、マージカスケードを許可します。
@ManyToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE }, fetch = FetchType.EAGER)
public AccountRole getAccountRole() {
return accountRole;
}
マージはこれを行うため:
エンティティが新しい場合は、persist()と同じです。ただし、エンティティがすでに存在する場合は、エンティティが更新されます。
処理中にトランザクションを終了したように見えるため、accountRole
が切り離されるか、他の理由ですでに切り離されています。
entityManager.merge(accountRole)
を呼び出す前にentityManager.persist(account)
を呼び出すと、修正されるはずです。
編集:残念ながら、accountRole
がDBにすでに存在するかどうかわからない場合は、クエリを実行して確認する必要があります。存在する場合は-マージし、存在しない場合は-持続します。それは確かに面倒ですが、私はまだより良い回避策を見ていません。
EDIT2:merge
メソッドに渡すエンティティは切り離されたままになります-管理対象エンティティはmerge
によって返されるため、最初にマージしてから、account
の参照をmerge
の戻り値に設定する必要があります。
データ化されたエンティティを渡して永続化することはできません。方法はありません。しかし、そうする必要はありません。
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