Performance Difference Between save() and saveAll() in Spring Data

1. Overview

In this quick tutorial, we’ll learn about the performance difference between save() and saveAll() methods in Spring Data.

2. Application

In order to test the performance, we’ll need a Spring application with an entity and a repository.

Let’s create a book entity:

@Entity
public class Book {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    private String title;
    private String author;

    // constructors, standard getters and setters
}

In addition, let’s create a repository for it:

public interface BookRepository extends JpaRepository<Book, Long> {
}

3. Performance

To test the performance, we’ll save 10,000 books using both methods.

First, we’ll use the save() method:

for(int i = 0; i < bookCount; i++) {
    bookRepository.save(new Book("Book " + i, "Author " + i));
}

Then, we’ll create a list of books and use the saveAll() method to save all of them at once:

List<Book> bookList = new ArrayList<>();
for (int i = 0; i < bookCount; i++) {
    bookList.add(new Book("Book " + i, "Author " + i));
}

bookRepository.saveAll(bookList);

In our tests, we noticed that the first method took around 2 seconds, and the second one took approximately 0.3 seconds.

Furthermore, when we enabled JPA Batch Inserts, we observed a decrease of up to 10% in the performance of the save() method, and an increase of up to 60% on the saveAll() method.

4. Differences

Looking into the implementation of the two methods, we can see that saveAll() iterates over each element and uses the save() method in each iteration. This implies that it shouldn’t be such a big performance difference.

Looking more closely, we observe that both methods are annotated with @Transactional.

Furthermore, the default transaction propagation type is REQUIRED, which means that, if not provided, a new transaction is created each time the methods are called.

In our case, each time we call the save() method, a new transaction is created, whereas when we call saveAll(), only one transaction is created, and it’s reused later by save().

This overhead translates into the performance difference that we noticed earlier.

Finally, the overhead is bigger when batching is enabled due to the fact that it’s done at the transaction level.

5. Conclusion

In this article, we’ve learned about the performance difference between the save() and saveAll() methods in Spring Data.

Ultimately, choosing whether to use one method over another can have a big performance impact on the application.

As always, the code for these examples is available over on GitHub.

Related posts:

Apache Commons Collections MapUtils
Java Program to Implement Binomial Heap
Hướng dẫn Java Design Pattern – Strategy
Assert an Exception is Thrown in JUnit 4 and 5
Converting String to Stream of chars
Java Program to Check Cycle in a Graph using Topological Sort
Spring Cloud – Tracing Services with Zipkin
Exploring the New Spring Cloud Gateway
Java Program to add two large numbers using Linked List
Intro to Inversion of Control and Dependency Injection with Spring
Remove All Occurrences of a Specific Value from a List
REST Web service: Upload và Download file với Jersey 2.x
Giới thiệu SOAP UI và thực hiện test Web Service
Java Program to Implement Interpolation Search Algorithm
Spring RestTemplate Error Handling
Java Program to Perform String Matching Using String Library
Java Program to Compare Binary and Sequential Search
Java Program to Perform Finite State Automaton based Search
Deploy a Spring Boot App to Azure
Creating Docker Images with Spring Boot
Java Program to Implement Meldable Heap
Java – Generate Random String
Hướng dẫn Java Design Pattern – Intercepting Filter
Implementing a Runnable vs Extending a Thread
Java Program to Check whether Graph is a Bipartite using 2 Color Algorithm
Quick Guide on Loading Initial Data with Spring Boot
Java Program to Perform Deletion in a BST
Java Program to Find the Median of two Sorted Arrays using Binary Search Approach
Java Program to Implement String Matching Using Vectors
Java Convenience Factory Methods for Collections
Java Program to Implement Floyd Cycle Algorithm
Hướng dẫn sử dụng Java String, StringBuffer và StringBuilder