Spring Boot JPA/JDBC batching findById works but findOneByX not working


I am using Spring Boot JPA, I have enabled batching by ensuring the following lines are in the my application.properties:


I now have a loop where I am doing a findById on an entity and then saving that entity like so:

var entity = dao.findById(id)
// Do some stuff
dao.save(entity) //This line is not really required but I am being explicit here

Putting the above in a loop I see that the save(update) statements are batched to the DB.
My issue is that if I do a findOneByX where X is a property on the entity then the batching does not work (batch size of 1), requests get sent one at a time i.e.:

var entity = dao.findOneByX(x)
// Do some stuff

Why is this happening? Is JPA/JDBC only equipped to batch when we findById only?



Refer to How to implement batch update using Spring Data Jpa?

  1. Fetch the list of entity you want to update to a list
  2. Update as desired
  3. Call saveAll

PS: beware of memory usage for this solution, when your list size is large.

Why findById and findOneByX behave differently?

As suggested by M. Deinum, hibernate will auto flush your change

prior to executing a JPQL/HQL query that overlaps with the queued entity actions

Since both findById and findOneByX will execute query, what is the different between them?

First, the reason to flush is to make sure session and Database are in same state, hence you can get consistent result from session cache(if available) and database.

When calling findById, hibernate will try to get it from session cache, if entity is not available, fetch it from database. While for findOneByX, we always need to fetch it from database as it is impossible to cache entity by X.

Then we can consider below example:

public class Student {
    private Long id;
    private String name;
    private int age;

Suppose we have
| id | name | age |
| :- | :— | :– |
| 1 | Amy | 10 |

public void findByIdAndUpdate() {
    dao.save(new Student(2L, "Dennis", 14));
    // no need to flush as we can get from session
    for (int i = 0; i < 100; i++) {
        Student dennis = dao.findById(2L).orElseThrow();

Will result in

412041 nanoseconds spent executing 2 JDBC batches;

1 for insert 1 one for update.

  • Hibernate: I’m sure that result can be fetch from session (without flush) or database if record is not in session, so let’s skip flushing as it is slow!
public void findOneByNameAndUpdate() {
    Student amy = dao.findOneByName("Amy");
    // this affect later query
    for (int i = 0; i < 100; i++) {
        // do you expect getting result here?
        Student tammy = dao.findOneByName("Tammy");
        // Hibernate not smart enough to notice this will not affect later result.

Will result in

13964088 nanoseconds spent executing 101 JDBC batches;

1 for first update and 100 for update in loop.

  • Hibernate: Hmm, I’m not sure if stored update will affect the result, better flush the update or I will be blamed by developer.

Answered By – samabcde

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published