我使用Spring數據與Hibernate作爲JPA實現。爲什麼在執行saveAndFlush之前,hibernate再次加載實體?
在某個時候,我加載一輛車,操縱它並保存。使用Spring JPA-Repository的代碼如下所示:
@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 ... <-- !!!
}
}
這適用於所有自動化測試和99%的生產。與事務日誌和SQL日誌是這樣的大多數時間:
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]
只有少數時候,Hibernate沒有一個SELECT 前右側的更新。
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]
有人可以解釋第二次選擇的情況嗎?我無法看到它。
不知道你的整個設置,但是如果Car有'子對象',那麼Hibernate可能會選擇檢查這些子對象是否已經存在於數據庫中,因此它不必保存它們(因爲它們是已經在那了)。 – Shadov
其他代碼應該在一個服務,這將是事務性的,而不是在你的控制器。現在,您擁有2個(隱式)事務,而所有事務都應在單個事務中。除此之外,你應該(需要)做一個'saveAndFlush'只需一個'save'就足夠了。 –