. Advertisement .
..3..
. Advertisement .
..4..
“Object references an unsaved transient instance – save the transient instance before flushing” is a common error that many programmers encounter. It shows up in many ways. What is the cause of it and how to solve it? Read on this article to find the best way for it.
When Do You Get The Error “Object references an unsaved transient instance – save the transient instance before flushing”?
When you run this program:
@Test
public void whenSaveEntitiesWithOneToOneAssociation_thenSuccess() {
User user = new User("Bob", "Smith");
Address address = new Address("London", "221b Baker Street");
user.setAddress(address);
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(user);
session.getTransaction().commit();
session.close();
}
You easily encounter the following error:
java.lang.IllegalStateException: org.hibernate.TransientObjectException: object references an unsaved
transient instance - save the transient instance before flushing
The user passes a transitory instance to a session method that expects a persistent instance, resulting in the TransientObjectException being thrown. Hibernate attempted to update the foreign key BRANCH ID in the Student table after initially inserting the Branch item in the database. However, there is no student record in the database yet. Therefore, in a persistence context, the Student entity state is temporary. As a result, the Branch object contains a reference to the transitory, unsaved instance (Student). Before Hibernate flushes the Branch, you must save the Student (temporary instance).
How To Solve The Error “Object references an unsaved transient instance – save the transient instance before flushing”?
Method 1: Use CascadeType.ALL to update the Branch entity
This is a common problem with Hibernate’s Parent and Child table association mappings. To resolve the issue, you must use CascadeType to perform the proper cascading operation to the reference in the Branch object.
Entity transitions are propagated from Parent to Child using CascadeType. The referred entities are also persisted before flushing, for instance, if you persist the parent entity. Let’s use CascadeType.ALL to update the Branch entity.
@Entity
public class Branch implements Serializable {
@Id
@Column(name="BRANCH_ID")
private int branchId;
@Column(name="BRANCH_NAME")
private String branchName;
@Column(name="BRANCH_SHORT_NAME")
private String branchShortName;
private String description;
//uni-directional one-to-many association to Student
@OneToMany(cascade = CascadeType.ALL , orphanRemoval = true)
@JoinColumn(name="BRANCH_ID")
private List<Student> students;
// .. omitted setters getters etc.
}
Let’s rerun the program and check the outcomes.
Hibernate: insert into Branch (BRANCH_NAME, BRANCH_SHORT_NAME, description) values (?, ?, ?)
Hibernate: insert into Student (CONTACT_NO, fname, lname) values (?, ?, ?)
Hibernate: insert into Student (CONTACT_NO, fname, lname) values (?, ?, ?)
Hibernate: update Student set BRANCH_ID=? where id=?
Hibernate: update Student set BRANCH_ID=? where id=?
Nov 19, 2020 11:21:43 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl stop
Now, you can see that updates to the Student table’s BRANCH ID foreign key come before updates to Student records.
Method 2: Use the appropriate CascadeType to update the Employee entity
Look at the following example:
@Entity
@Table(name = "employee")
public class Employee {
...
@ManyToOne
@Cascade(CascadeType.SAVE_UPDATE)
@JoinColumn(name = "department_id")
private Department department;
...
}
Update the Department entity to utilize the correct CascadeType for the Department-Employees association as well:
@Entity
@Table(name = "department")
public class Department {
…
@OneToMany(mappedBy = "department", cascade = CascadeType.ALL, orphanRemoval = true)
private Set employees = new HashSet<>();
…
}
Now, suppose you connect a new Department instance with a new Employee instance and save the Employee instance. In that case, the Hibernate session will keep the associated Department instance by using the @Cascade(CascadeType.SAVE UPDATE) on the Employee-Department association.
By using cascade = CascadeType in a same manner, t he Hibernate session will cascade all actions from a Department to the related Employee based on the Department-Employee link (s). For instance, deleting a Department will also delete any linked Employees.
Method 3: Use appropriate CascadeTypes to update the Author entity
Another way for you to solve the error “Object references an unsaved transient instance – save the transient instance before flushing” is using appropriate CascadeTypes to update the Author entity. Look at this example:
@Entity
@Table(name = "author")
public class Author {
...
@ManyToMany
@Cascade({ CascadeType.SAVE_UPDATE, CascadeType.MERGE, CascadeType.PERSIST})
@JoinColumn(name = "book_id")
private Set<Book> books = new HashSet<>();
...
}
Let’s do the same thing with the Book object and change it to utilize the correct CascadeTypes for the Books-Authors association:
@Entity
@Table(name = "book")
public class Book {
...
@ManyToMany
@Cascade({ CascadeType.SAVE_UPDATE, CascadeType.MERGE, CascadeType.PERSIST})
@JoinColumn(name = "author_id")
private Set<Author> authors = new HashSet<>();
...
}
Be aware that the CascadeType is ineffective. Because you don’t want to delete the Book if an Author is deleted, and vice versa, ALL are in a @ManyToMany association.
Method 4: Use the appropriate CascadeType to update the User entity
Let’s use the appropriate CascadeType to update the User entity as the following example:
@Entity @Table(name = "user")
public class User {
...
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "address_id", referencedColumnName = "id")
private Address address;
...
}
The linked Address will now also be saved or deleted whenever you save or delete a User in a Hibernate session, and the session will no longer raise the TransientObjectException.
Conclusion
We hope you will enjoy our article about the error. With this knowledge, we know that you can fix your issue: “Object references an unsaved transient instance – save the transient instance before flushing” quickly by following these steps! If you still have any other questions about fixing this syntax error, please leave a comment below. Thank you for reading!
Read more
→ How to solve “ReferenceError: window is not defined at object” in Node.js
Leave a comment