1. Overview

In this quick tutorial, we’ll discuss the difference between the save() and saveAndFlush() methods in Spring Data JPA.

Even though we use both of these methods for saving entities to the database, there are some fundamental differences.

2. Example Application

First, let’s see how to use the save() and saveAndFlush() methods with an example. We’ll start by creating an entity class:

@Entity
public class Employee {

    @Id
    private Long id;
    private String name;
    
    // constructors
    // standard getters and setters
}

Next, we’ll create a JPA repository for the CRUD operations on the Employee entity class:

public interface EmployeeRepository extends JpaRepository<Employee, Long> {
}

3. The save() Method

As the name depicts, the save() method allows us to save an entity to the DB. It belongs to the CrudRepository interface defined by Spring Data. Let’s see how we can use it:

employeeRepository.save(new Employee(1L, "John"));

Normally, Hibernate holds the persistable state in memory. The process of synchronizing this state to the underlying DB is called flushing.

When we use the save() method, the data associated with the save operation won’t be flushed to the DB unless, and until, an explicit call to the flush() or commit() method is made.

If we use JPA implementations like Hibernate, then that specific implementation will be managing the flush and commit operations.

One thing we have to keep in mind here is that, if we decide to flush the data by ourselves without committing it, then the changes won’t be visible to the outside transaction unless a commit call is made in this transaction or the isolation level of the outside transaction is READ_UNCOMMITTED.

4. The saveAndFlush() Method

Unlike save(), the saveAndFlush() method flushes the data immediately during the execution. This method belongs to the JpaRepository interface of Spring Data JPA. Here’s how we use it:

employeeRepository.saveAndFlush(new Employee(2L, "Alice"));

Normally, we use this method when our business logic needs to read the saved changes at a later point during the same transaction, but before the commit.

For instance, imagine a scenario where we have to execute a stored procedure that expects a property of the entity that we’re going to save. In this case, the save() method won’t work, since the changes aren’t in sync with the DB and the stored procedure doesn’t know about the changes. The saveAndFlush() method is perfectly suited for this kind of scenario.

5. Conclusion

In this brief article, we focused on the difference between the Spring Data JPA save() and saveAndFlush() methods.

In most cases, we’ll use the save() method. But occasionally, we may need to use the saveAndFlush() method as well for specific use cases.

As usual, the example we’ve discussed here can be found over on GitHub.