OSIV和JPA实体侦听器@PreUpdate之间的关系

问题描述 投票:1回答:1
@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?

spring spring-boot jpa event-listener ipreupdateeventlistener
1个回答
1
投票

这是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

© www.soinside.com 2019 - 2024. All rights reserved.