Java 有没有办法将分离的对象传递给JPA persist?(已分离的实体传递到持久化)
我有两个实体:Java 有没有办法将分离的对象传递给JPA persist?(已分离的实体传递到持久化),java,hibernate,jpa,entitymanager,Java,Hibernate,Jpa,Entitymanager,我有两个实体:Account和AccountRole public class Account { private AccountRole accountRole; @ManyToOne(cascade = CascadeType.PERSIST, fetch = FetchType.EAGER) public AccountRole getAccountRole() { return accountRole; } 我读到:据我所知,我必须从两个方向设置
Account
和AccountRole
public class Account {
private AccountRole accountRole;
@ManyToOne(cascade = CascadeType.PERSIST, fetch = FetchType.EAGER)
public AccountRole getAccountRole() {
return accountRole;
}
我读到:据我所知,我必须从两个方向设置实体值,以便我在setter中执行的操作。
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
仍然有错误
org.hibernate.PersistentObjectException: detached entity passed to persist: foo.bar.pojo.AccountRole
看起来您在处理过程中离开了事务,因此
accountRole
被分离,或者由于其他原因它已经被分离
在调用entityManager.persist(account)
之前调用entityManager.merge(accountRole)
应该可以解决这个问题
编辑:很遗憾,如果无法确定数据库中是否已经存在accountRole
,则必须通过查询进行检查。如果存在-合并,如果不存在-持久化。这确实很麻烦,但我还没有看到更好的解决办法
EDIT2:传递给合并
方法的实体将保持分离状态-托管实体将由合并
返回,因此您需要首先合并,然后将帐户
上的引用设置为合并的返回值,只需替换
entityManager.persist(account);
与:
并允许合并级联:
@ManyToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE }, fetch = FetchType.EAGER)
public AccountRole getAccountRole() {
return accountRole;
}
因为“合并”会执行以下操作:
如果实体是新的,则它与persist()相同。
但如果您的实体已经存在,它将更新它
您不能传递一个datached实体来持久化,这是不可能的。但是你不需要
您希望将帐户
独立于帐户角色
(已被持久化)进行持久化。为了实现这一点,只需从子实体中的@ManyToOne
中删除级联(本例中为帐户
):
请参见我在此处的解释,原因是:在极少数情况下,数据库中不存在AccountRole
,因此在执行em.persist
时,它会将帐户和AccountRole持久化,一切正常。现在,当我发现自己在这种情况下使用您的代码时,它正在尝试将AccountRole
两次添加到数据库中,首先使用merge,使用succeedes,然后使用Persiste,从而给我重复键值冲突错误
,有什么建议吗?问题是,有时角色不存在。一种解决方案可能是,如果角色不存在,将整个该死的事情持续下去,但如果角色确实存在,首先将其合并,但这似乎太麻烦了,不是吗?@Jaanus-唉,你是对的:)我已经相应地编辑了答案。只是试了一下,同样的事情。。entityManager.merge(account.getAccountRole());entityManager.persist(帐户)代码>和相同的错误:分离的实体传递给persist:ee.sellin.vahvagame.pojo.AccountRole
。。哦boy@Jaanus-JPA在合并方面有一个怪癖-我忘了提,对不起。请参阅第二次编辑。还要注意,persist()
将使您传递的对象成为托管实体,但是,merge将返回您传递的对象的托管副本。因此,如果您在合并后需要一个托管实体,您应该执行account=entityManager.merge(account)
也可以查看一下
entityManager.merge(account);
@ManyToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE }, fetch = FetchType.EAGER)
public AccountRole getAccountRole() {
return accountRole;
}
public class Account {
private AccountRole accountRole;
@ManyToOne // no cascading here!
public AccountRole getAccountRole() {
return accountRole;
}