@Transactional
public void updateUser(User user) {
productRepository.findByName("AAA"); // (1)
userRepository.save(user); // (2)
}
@Entity
@EntityListener(UserListener.class)
class User {...}
class UserListener{
@PreUpdate
public void onPreUpdate() { ... }
}
[当OSIV = true时,(1)行-> [@PreUpdate
被调用 /(2)行-> @PreUpdate
调用
[当OSIV = false时,(1)行-> [@PreUpdate
not found] /(2)行-> @PreUpdate
调用
为什么会这样?为什么在执行(1)行时调用@preupdate?
这是JPA 2.0规范:
PreUpdate和PostUpdate回调发生在数据库更新操作分别对实体数据。这些数据库实体状态更新时或它们发生时可能会发生操作状态刷新到数据库时可能会发生(可能是在交易结束时)。
请记住,@ PreUpdate它将始终为所有读/写事务触发,这是因为在读/写事务上使用FlushMode,而在只读事务上则从来没有(因为FlushMode.NEVER)
无OSIV
当您调用updateUser
时,由于@Transactional
,因此您具有读/写事务(外部事务)。
现在,findByName
是事务性的,但标记为readonly(默认情况下,所有查找器均为readonly)。当前事务被挂起,并执行新的readonly。这就是为什么(1)行不会触发@Preupdate
。
此后,将继续当前的读/写事务(save
不是只读的,并且触发了@Preupdate
。
With OSIV
这种情况下,当前请求仅绑定一个读/写事务。 findByName
在读/写事务中执行,因此(1)行确实触发了@Preupdate