打开的事务看不到另一个事务提交的数据

Posted

技术标签:

【中文标题】打开的事务看不到另一个事务提交的数据【英文标题】:Open transaction cannot see committed data by another transaction 【发布时间】:2021-08-28 03:50:26 【问题描述】:

我有一个 Spring Boot 应用程序,在这个 REST 调用中调用了一个 REST 服务,完成了两个单独的 DB 操作(正在使用 Spring Data JPA)。第一个更新一些数据库表,第二个从所述表中读取并执行一些操作。

@GetMapping("/process")
public void process()
   service1.updateValues();//updates the values
   service2.readValuesAndProcess();//reads those updated values and execute some logic and persist at the end

现在的问题是;

第二种方法似乎没有读取在第一种方法中更新的更新值,而是以某种方式读取更新之前的值。这两个方法都是@Transactional,实体是@versioned,当调用保存操作时会抛出ObjectOptimisticLockingFailureException

在 application.properties 中 spring.jpa.open-in-view 属性为 true,当我将其更改为 false 时,一切都按预期工作,但我不能保证我不会在其他地方得到 lazyInitializationException

我尝试将事务方法传播更改为 REQUIRES_NEW,但没有任何变化。

【问题讨论】:

如何更新 updateValues() 方法中的值?如果您使用 spring.jpa.open-in-view = true,那么在您的请求中,只有一个实体管理器用于您的所有语句。因此,如果您保存的对象仍在实体管理器缓存中,则可能不会从数据库中重新加载它。顺便说一句, spring.jpa.open-in-view = true 被认为是反模式。看到这个:***.com/questions/30549489/… 是的,我们使用 spring.jpa.open-in-view = true,您的见解是正确的。实体是通过来自另一个实体的@onetoone 关系加载的,并且不会使用 save 进行更新,而是使用自定义 hql 查询进行更新,因此不会更新一级缓存。因此,当执行第二次选择时,将从一级缓存中获取实体。 【参考方案1】:

updateValues 的更新进展如何?并发用户的代码线程安全吗? 丢失更新可能会导致JPA 抛出ObjectOptimisticLockingFailureException,这是一件好事。

有关乐观锁定的更多信息,请阅读此内容:Optimistic Locking in JPA | Baeldung。

【讨论】:

【参考方案2】:

如果 updateValues() 被注释为@Transactional,它应该可以工作。在 updatevalues() 结束时,更改将在春季实际提交到数据库

【讨论】:

以上是关于打开的事务看不到另一个事务提交的数据的主要内容,如果未能解决你的问题,请参考以下文章

事务<查询不到同一调用方法其它事务提交的更新;解决方案

一个事务中先插入数据,然后再查询所有数据,能查到刚才的记录吗

求数据库大神,mysql事务隔离级别repeatable-read 详解

在另一个事务中提交数据对象后在一个事务中读取数据对象 - 脏读?

jpql sql在同一个事务中

mysql一致性读