JPA/Hibernate: detached entity passed to persist
What is a detached entity passed to persist? what is that detached entity the message talks about?
I have a JPA-persisted object model that contains a many-to-one relationship: an Account has many Transactions. A Transaction has one Account.
Here's a snippet of the code:
@Entity
public class Transaction {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@ManyToOne(cascade = {CascadeType.ALL},fetch= FetchType.EAGER)
private Account fromAccount;
....
@Entity
public class Account {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@OneToMany(cascade = {CascadeType.ALL},fetch= FetchType.EAGER, mappedBy = "fromAccount")
private Settransactions;
I am able to create an Account object, add transactions to it, and persist the Account object correctly. But, when I create a transaction, using an existing already persisted Account, and persisting the Transaction, I get an exception:
Caused by: org.hibernate.PersistentObjectException: detached entity passed to persist: com.paulsanwald.Account at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:141)
So, I am able to persist an Account that contains transactions, but not a Transaction that has an Account. I thought this was because the Account might not be attached, but this code still gives me the same exception:
if (account.getId()!=null) {
account = entityManager.merge(account);
}
Transaction transaction = new Transaction(account,"other stuff");
// the below fails with a "detached entity" message. why?
entityManager.persist(transaction);
How can I correctly save a Transaction, associated with an already persisted Account object?
This is a standard bidirectional compatibility problem. It is well discussed in this link as well as this link.
As per the provisions in the previous 2 links you require to fix your setters in both parties of the bidirectional connection. An example setter for the One side is in this link.
A standard-setter for the Many sides is in this link.
After you change your setters you want to declare the Entity access type to be "Property". Best practice to declare the "Property" access-type is to move ALL the explanations from the member properties to the corresponding getters. A big word of warning is not to mix "Field" and "Property" access standards within the entity class unless the behavior is undefined by the JSR-317 specs.
A detached entity (a.k.a. a detached object) is an object that has the same ID as an entity in the persistence store but that is no longer part of a persistence context (the scope of an EntityManager session).