detached entity passed to persist error with JPA/EJB code
Let's say you have two entities Album
and Photo
. Album contains many photos, so it's a one to many relationship.
Album class
@Entity
public class Album {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
Integer albumId;
String albumName;
@OneToMany(targetEntity=Photo.class,mappedBy="album",cascade={CascadeType.ALL},orphanRemoval=true)
Set<Photo> photos = new HashSet<Photo>();
}
Photo class
@Entity
public class Photo{
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
Integer photo_id;
String photoName;
@ManyToOne(targetEntity=Album.class)
@JoinColumn(name="album_id")
Album album;
}
What you have to do before persist or merge is to set the Album reference in each photos.
Album myAlbum = new Album();
Photo photo1 = new Photo();
Photo photo2 = new Photo();
photo1.setAlbum(myAlbum);
photo2.setAlbum(myAlbum);
That is how to attach the related entity before you persist or merge.
PersistentObjectException: detached entity passed to persist thrown by JPA and Hibernate
This is a typical bidirectional consistency problem. It is well discussed in this link as well as this link.
As per the articles in the previous 2 links you need to fix your setters in both sides of the bidirectional relationship. An example setter for the One side is in this link.
An example setter for the Many side is in this link.
After you correct your setters you want to declare the Entity access type to be "Property". Best practice to declare "Property" access type is to move ALL the annotations from the member properties to the corresponding getters. A big word of caution is not to mix "Field" and "Property" access types within the entity class otherwise the behavior is undefined by the JSR-317 specifications.
detached entity passed to persist Kotlin
You've defined the id field as auto generated but assigned it a default value. When hibernate tries to persist it, it thinks that the object represents an underlying row in database because it already has an id. So, it considers it a detached object.
The persist() method doesn't work on a detached object.
You can set the default value of id to null to resolve this issue.
detached entity passed to persist - on findByMethod
This behavior depends on FlushMode of EntityManager.
The FlushMode
defines when new entities and your changes on existing ones get written to the database, in other words, defines when flush()
operation is performing.
The flush process synchronizes database state with session state by
detecting state changes and executing SQL statements.
The JPA specification defines the FlushModeType.AUTO as the default flush mode. It flushes the persistence context in next situations:
- before the transaction gets committed
- before executing a query that uses any database table for which your persistence context contains any pending changes.
According to documentation:
AUTO
The Session is sometimes flushed before query execution in order to
ensure that queries never return stale state. This is the default
flush mode.
Summary:
So in your example, we have default FlushMode.AUTO
, during the query execution framework performs flush()
operation, this is the reason.
FlushMode.AUTO
is fixing consistency issues on a query basis, but on other hand can lead to unpredictable flush operations and as result performance problems in the case of huge services. I recommend to change FlushMode
to COMMIT
, when you do not need to resolve consistency issues. The FlushModeType.COMMIT requires a flush before committing the transaction but doesn’t define what needs to happen before executing a query. Executing any query doesn’t flush any pending changes.
Changing FlushMode
:
1. Globally for server add to properties
spring.jpa.properties.org.hibernate.flushMode=COMMIT
2. Set for specific query
Query quey = entityManager.createQuery("SELECT * from Foo");
quey.setFlushMode(FlushModeType.COMMIT);
3. Set for Session
Inject EntityManager
into your service.
@Transactional
fun save(name:String, city: String){
entityManager.setFlushMode(FlushModeType.COMMIT)
...
}
Detailed described at How does AUTO flush strategy work in JPA and Hibernate
Related Topics
Best Way to Make Java's Modulus Behave Like It Should with Negative Numbers
Get All of the Classes in the Classpath
Take N Random Elements from a List<E>
Configure Hibernate (Using JPA) to Store Y/N for Type Boolean Instead of 0/1
Converting JSON to Xls/CSV in Java
How to Use Regex in String.Contains() Method in Java
Why Can't I Use a Type Argument in a Type Parameter with Multiple Bounds
How to Call a Superclass Method Using Java Reflection
Can "This" Ever Be Null in Java
How to Deploy Javafx Application, Create Jar and Self-Contained Applications and Native Installers
Has Been Compiled by a More Recent Version of the Java Runtime (Class File Version 57.0)
Spring Data JPA Update @Query Not Updating
Java 8: Difference Between Method Reference Bound Receiver and Unbound Receiver
How to Detect Submit Button Clicked in Multiple Submit Buttons Scenario in Single Action Class
Jdk9: an Illegal Reflective Access Operation Has Occurred. Org.Python.Core.Pysystemstate