简体   繁体   English

有没有办法将分离的对象传递给JPA持久化? (传递给持久化的分离实体)

[英]Is there a way to pass detached object to JPA persist? (detached entity passed to persist)

I have 2 entities : Account and AccountRole . 我有2个实体: AccountAccountRole

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

Problem comes when I take the accountRole from database and try to persist my Account . 当我从数据库中获取accountRole并尝试保留我的Account At this point I just created my account and role already exists in db. 此时我刚创建了我的帐户,角色已经存在于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

I read this : JPA/Hibernate: detached entity passed to persist And what I understood, I must set the entities values from both direction, so that what I am doing in my setter. 我读到这个: JPA / Hibernate:传递给persist的分离实体 我理解的是,我必须从两个方向设置实体值,以便我在我的setter中做什么。

Still getting error. 仍然有错误。

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

Just replace the 只需更换

entityManager.persist(account);

with: 有:

entityManager.merge(account);

And allow merge cascading: 并允许合并级联:

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

Because merge does this: 因为合并这样做:

If your entity is new, it's the same as a persist(). 如果您的实体是新实体,则它与persist()相同。 But if your entity already exists, it will update it. 但是如果您的实体已经存在,它将更新它。

It looks like you leave the transaction during your processing, so the accountRole gets detached, or it is already detached for other reasons. 看起来您在处理期间离开了事务,因此accountRole被分离,或者由于其他原因已经分离。

A call to entityManager.merge(accountRole) before calling entityManager.persist(account) should fix it. 在调用entityManager.merge(accountRole)之前调用entityManager.merge(accountRole) entityManager.persist(account)应该修复它。

EDIT: Unfortunately, if you cannot be sure if the accountRole already exists in the DB, you will have to check it by querying. 编辑:不幸的是,如果您无法确定数据库中是否已存在accountRole ,则必须通过查询来检查它。 If it exists - merge, if not - persist. 如果存在 - 合并,如果不存在 - 继续。 It is indeed a hassle, but I have not yet seen a better workaround. 这确实很麻烦,但我还没有看到更好的解决方法。

EDIT2: The entity you pass to the merge method will remain detached - the managed entity will be returned by the merge , so you would need to merge first, then set the reference on the account to the return value of the merge . EDIT2:您传递给实体merge方法将保持断开状态-托管实体将被返回的merge ,所以你需要首先合并,然后在基准设置account到的返回值merge

You cannot pass a datached entity to persist, there is no way. 你不能传递一个数据库实体来坚持,没有办法。 But you don't need to. 但你不需要。

You want to persist an Account independently of the AccountRole (which is already persisted). 您希望独立于AccountRole (已保留)持久保存Account In order to achieve this, simply remove cascading from @ManyToOne in the child entity ( Account in this case): 为了实现这一点,只需@ManyToOne中的@ManyToOne中删除级联 (在本例中为Account ):

public class Account {
    private AccountRole accountRole;

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

See my explanation here, why: https://stackoverflow.com/a/54271569/522578 请参阅我的解释,原因如下: https//stackoverflow.com/a/54271569/522578

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM