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

感情迁移 提交于 2019-11-29 01:35:23

问题


I have 2 entities : Account and 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;
    }

Problem comes when I take the accountRole from database and try to persist my Account. At this point I just created my account and role already exists in 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.

Still getting error.

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

回答1:


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(). But if your entity already exists, it will update it.




回答2:


It looks like you leave the transaction during your processing, so the accountRole gets detached, or it is already detached for other reasons.

A call to entityManager.merge(accountRole) before calling entityManager.persist(account) should fix it.

EDIT: Unfortunately, if you cannot be sure if the accountRole already exists in the DB, you will have to check it by querying. 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.




回答3:


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). In order to achieve this, simply remove cascading from @ManyToOne in the child entity (Account in this case):

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/questions/13835980/is-there-a-way-to-pass-detached-object-to-jpa-persist-detached-entity-passed-t

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!