Reputation: 4402
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
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
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