Hibernate save(), update() and saveOrUpdate()

Learn the different methods for persisting and updating the entity states in the database using Hibernate Session APIs to use save(), update() and saveOrUpdate() methods under different usecases.

Starting Hibernate 6.0, all save(), update() and saveOrUpdate() methods have been marked deprecated in favor of Jakarta persistence API provided persist() and merge() methods.

1. Entity Lifecycle States

A JPA or Hibernate entity can be in one of the following four states:

  • Transient (New)
  • Managed (Persistent)
  • Detached (Not associated with any Session)
  • Removed (Deleted)

The Hibernate Session provides state transition methods like savesaveOrUpdate and update apart from methods implemented from JPA specs, for example, persist(), merge() and remove().

2. Using Session.save()

2.1. With Transient Entity

The save() method is used make a TRANSIENT entity PERSISTENT by associating it with either an org.hibernate.Session. Before persisting the entity, it assigns a generated identifier to the ID field.

The save() method returns the generated identifier so it has to immediately execute the SQL INSERT statement (it does not matter if we are inside or outside of a transaction) because identifiers are generated by the database during the INSERT query execution only.

Note that if we call save() outside the transaction then associated entities may not be inserted immediately because save() has to return the generated identifier only for the main entity. This can cause data inconsistency if we forget to flush the changes or some application error happens.

EmployeeEntity employee = new EmployeeEntity();
employee.setEmail("demo-user@email.com");
employee.setFirstName("demo");
employee.setLastName("user");

Long id = session.save(employee);

This will execute the SQL INSERT statement.

Hibernate: insert into Employee (ID, email, firstName, lastName) values (default, ?, ?, ?)

2.2. With Persistent Entity

For PERSISTENT entities, save() works as update() method and executes UPDATE SQL queries.

Long id = session.save(employee);

emp.setLastName("userOne");
session.save(employee);

Check out that the second statement is UPDATE query.

Hibernate: insert into Employee (ID, email, firstName, lastName) values (default, ?, ?, ?)
Hibernate: update Employee set lastName=? where ID=?

2.3. With Detached Entity

A detached entity already has the identifier associated with it so the behavior of the save() method depends on the ID generation strategy when executing the INSERT query.

  • If the strategy is GenerationType.SEQUENCE then a new identifier will be generated and a duplicate record will be inserted into the database.
  • If the strategy is GenerationType.IDENTITY then we will get ConstraintViolationException for duplicate primary key violation.

3. Using update()

The update() is pretty much a simpler method.

  • It executes the SQL UPDATE query for PERSISTENT entities.
  • It throws TransientObjectException if there is no identifier associated (transient entity).
EmployeeEntity emp = new EmployeeEntity();
emp.setEmail("demo-user@mail.com");
emp.setFirstName("demo");
emp.setLastName("user");

//Transient entity
session.update(emp);

It will throw an exception.

org.hibernate.TransientObjectException: The given object has a null identifier: 
  com.howtodoinjava.basics.entity.EmployeeEntity

To correctly update an entity, make it persistent first using save() or persist() methods.

EmployeeEntity emp = new EmployeeEntity();
emp.setEmail("demo-user@mail.com");
emp.setFirstName("demo");
emp.setLastName("user");

//Transient entity
session.save(emp);

emp.setLastName("userOne");

//Persistent entity
session.update(emp);

Now notice the logs.

Hibernate: insert into Employee (email, firstName, lastName, ID) values (?, ?, ?, ?)
Hibernate: update Employee set lastName=? where ID=?

4. Using saveOrUpdate()

The saveOrUpdate(), as the name implies, works as either save() or update() on the basis of the ID field present in the entity or not. In most cases, it is the preferred method to save().

  • If ID is not present then save() is called.
  • If ID is present then update() is called.

The saveOrUpdate() can be used with PERSISTENT as well as TRANSIENT entities both. Persistent entities will get updated, and transient entities will be inserted into the database.

EmployeeEntity emp = new EmployeeEntity();
emp.setEmail("demo-user@mail.com");
emp.setFirstName("demo");
emp.setLastName("user");

//Transient entity
session.saveOrUpdate(emp);

emp.setLastName("userOne");

//Persistent entity
session.saveOrUpdate(emp);

Check out the logs.

Hibernate: insert into Employee (email, firstName, lastName, ID) values (?, ?, ?, ?)
Hibernate: update Employee set lastName=? where ID=?

5. Conclusion

  • The save() method INSERTs an object in the database. It will persist the given transient instance, first assigning a generated identifier. It returns the id of the entity created.
  • The saveOrUpdate() calls either save() or update() on the basis of identifier exists or not. e.g if identifier does not exist, save() will be called or else update() will be called.

Happy Learning !!

Leave a Reply

19 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions, and frequently asked interview questions.