How to fix the Hibernate "object references an unsaved transient instance - save the transient instance before flushing" error
You should include cascade="all"
(if using xml) or cascade=CascadeType.ALL
(if using annotations) on your collection mapping.
This happens because you have a collection in your entity, and that collection has one or more items which are not present in the database. By specifying the above options you tell hibernate to save them to the database when saving their parent.
I believe this might be just repeat answer, but just to clarify, I got this on a @OneToOne
mapping as well as a @OneToMany
. In both cases, it was the fact that the Child
object I was adding to the Parent
wasn't saved in the database yet. So when I added the Child
to the Parent
, then saved the Parent
, Hibernate would toss the "object references an unsaved transient instance - save the transient instance before flushing"
message when saving the Parent.
Adding in the cascade = {CascadeType.ALL}
on the Parent's
reference to the Child
solved the problem in both cases. This saved the Child
and the Parent
.
Sorry for any repeat answers, just wanted to further clarify for folks.
@OneToOne(cascade = {CascadeType.ALL})@JoinColumn(name = "performancelog_id")public PerformanceLog getPerformanceLog() { return performanceLog;}
Introduction
When using JPA and Hibernate, an entity can be in one of the following 4 states:
- New - A newly created object that hasn’t ever been associated with a Hibernate Session (a.k.a Persistence Context) and is not mapped to any database table row is considered to be in the New or Transient state.
To become persisted we need to either explicitly call the persist
method or make use of the transitive persistence mechanism.
- Persistent - A persistent entity has been associated with a database table row and it’s being managed by the currently running Persistence Context.
Any change made to such an entity is going to be detected and propagated to the database (during the Session flush-time).
Detached - Once the currently running Persistence Context is closed all the previously managed entities become detached. Successive changes will no longer be tracked and no automatic database synchronization is going to happen.
Removed - Although JPA demands that managed entities only are allowed to be removed, Hibernate can also delete detached entities (but only through a
remove
method call).
Entity state transitions
To move an entity from one state to the other, you can use the persist
, remove
or merge
methods.
Fixing the problem
The issue you are describing in your question:
object references an unsaved transient instance - save the transient instance before flushing
is caused by associating an entity in the state of New to an entity that's in the state of Managed.
This can happen when you are associating a child entity to a one-to-many collection in the parent entity, and the collection does not cascade
the entity state transitions.
So, you can fix this by adding cascade to the entity association that triggered this failure, as follows:
The @OneToOne
association
@OneToOne( mappedBy = "post", orphanRemoval = true, cascade = CascadeType.ALL)private PostDetails details;
Notice the
CascadeType.ALL
value we added for thecascade
attribute.
The @OneToMany
association
@OneToMany( mappedBy = "post", orphanRemoval = true, cascade = CascadeType.ALL)private List<Comment> comments = new ArrayList<>();
Again, the CascadeType.ALL
is suitable for the bidirectional @OneToMany
associations.
Now, in order for the cascade to work properly in a bidirectional, you also need to make sure that the parent and child associations are in sync.
The @ManyToMany
association
@ManyToMany( mappedBy = "authors", cascade = { CascadeType.PERSIST, CascadeType.MERGE })private List<Book> books = new ArrayList<>();
In a @ManyToMany
association, you cannot use CascadeType.ALL
or orphanRemoval
as this will propagate the delete entity state transition from one parent to another parent entity.
Therefore, for @ManyToMany
associations, you usually cascade the CascadeType.PERSIST
or CascadeType.MERGE
operations. Alternatively, you can expand that to DETACH
or REFRESH
.