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

Jaanus picture Jaanus · Dec 12, 2012 · Viewed 26.9k times · Source

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

Answer

Jaanus picture Jaanus · Dec 12, 2012

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.