Marcel
Marcel

Reputation: 4402

Why is hibernate loading an entity again before doing saveAndFlush?

I'm using Spring Data with Hibernate as JPA-implementation.

At some point I load a car, manipulate it and save it. Using the Spring JPA-Repository the code looks like this:

@Entity @DynamicUpdate @DynamicInsert
public class Car{ 
    @PostLoad
    void postLoad(){ log.debug("post load"); }

    @PrePersist @PreUpdate
    void preSave(){ log.debug("prePersist/preUpdate"); }

    /*..*/
}

@Repository
public interface CarRepository extends JpaRepository<Car, Integer>{}

@Controller
public CarController{
    public void businessLogic(){
        Car car = carRepo.findOne(1);  // SELECT ...
        log.debug("Car loaded");
        car.setColor("red");
        // ...
        carRepo.saveAndFlush(car);     // UPDATE car SET ... <-- !!!
    }
}

This works fine in all automated tests and in 99% in production. The logs with transaction logs and SQL look like this most of the time:

SQL: select ... from Car ...
Car: post load
Car loaded
Getting transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.saveAndFlush]
Car: prePersist/preUpdate
SQL: update Car set ...
Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.saveAndFlush]

There are only a few times when hibernate does a SELECT right before the UPDATE.

SQL: select ... from Car ...
Car: post load
Car loaded
Getting transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.saveAndFlush]
SQL: select ... from Car ...
Car: post load
Car: prePersist/preUpdate 
SQL: update Car set ...
Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.saveAndFlush]

Can someone explain the circumstances under which a second select is done? I'm not able to see it.

Upvotes: 0

Views: 1668

Answers (2)

Kayaman
Kayaman

Reputation: 73558

That's Hibernate doing dirty-checking. It re-loads the entity to compare it with any changes you're saving.

There are several ways to lessen its performance impact, such as using versioning: Java - JPA - @Version annotation or bytecode modification to make the dirty checking more efficient.

Upvotes: 1

Ermintar
Ermintar

Reputation: 1393

Hibernate does dirty checking every time you have a SELECT statement after some save/delete operation in the same transaction. Dirty checking is done to clear 1st/2-nd level caches. Roughly, Hibernate looks up through HashMap, containing names of cached tables and compares with tables used in your request.

Upvotes: 0

Related Questions