Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 有没有办法将分离的对象传递给JPA persist?(已分离的实体传递到持久化)_Java_Hibernate_Jpa_Entitymanager - Fatal编程技术网

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;
    }