我有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
答案 0 :(得分:16)
只需替换
即可entityManager.persist(account);
使用:
entityManager.merge(account);
并允许合并级联:
@ManyToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE }, fetch = FetchType.EAGER)
public AccountRole getAccountRole() {
return accountRole;
}
因为合并这样做:
如果您的实体是新实体,则它与persist()相同。 但是,如果您的实体已经存在,它将更新它。
答案 1 :(得分:3)
看起来您在处理过程中会离开事务,因此accountRole
会被分离,或者由于其他原因而已经分离。
在致电entityManager.merge(accountRole)
之前致电entityManager.persist(account)
应修复此问题。
编辑:不幸的是,如果您无法确定数据库中是否已存在accountRole
,则必须通过查询来检查它。如果存在 - 合并,如果不存在 - 继续。这确实很麻烦,但我还没有看到更好的解决方法。
EDIT2:您传递给merge
方法的实体将保持分离 - 管理实体将由merge
返回,因此您需要先合并,然后在{上设置参考{1}}到account
的返回值。
答案 2 :(得分: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