问题描述
最近在生产环境中碰到一个并发更新的错误,具体报错信息为:
javax.persistence.OptimisticLockException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1;
看报错信息判断是并发更新失败引起的,而业务表里刚好有个version字段,通过javax.persistence.Version进行注解,该注解用于数据库乐观锁版本控制。
但问题在于线上虽然发布了新版本,但是并没有对报错的相关代码有任何变更。最后经过一系列验证发现,该报错是由hibernatete包升级引起的。
具体来说,就是项目使用了Quarkus框架,并在本次发布时将其由2.13.3版本升级到了2.15.3版本。相应的,quarkus-spring-data-jpa也做了同样的升级。而quarkus-spring-data-jpa 中引用了hibernate-core的包,且在升级过程中由5.6.15版本降低到了5.6.14版本。
需要注意的是,并不是Quarkus版本越高,依赖的其他三方包的版本就越高。Quarkus的稳定版本是一直在持续维护的,也就是说,有可能低版本的quarkus在维护后比高版本的quarkus使用的三方包的版本要高。
查询官方release note可以看到,hibernate 5.6.15版本修复了一个bug,描述如下:

这个bug就是说将属性设置为当前的属性时会导致不必要的更新。继续进入HHH-16049报告页可以看到,该bug可能是在解决HHH-15634问题时引入的:

在github上该bug描述如下:

在Quarkus中,除了2.14.1-2.16.1引用了hibernate 5.6.14之外,其他的版本都没有影响。
解决办法也很简单,那就是再引入hibernate 5.6.15版本,这样就可以保证系统优先使用Hibernate 5.6.15了,该版本不存在此bug。
JPA和Spring Data JPA
JPA(Java Persistence API)即Java持久化API,是一套基于ORM的思想的规范。换句话说,JPA只有定义没有实现,其内部只有一系列接口和抽象类。
JPA是由具体的db访问框架来实现的,如Hibernate,EclipseLink,OpenJPA等。
那Spring Data JPA又是什么东西呢?

文章讨论了一次生产环境中遇到的并发更新异常,具体表现为OptimisticLockException。问题源于Quarkus框架升级后,其依赖的Hibernate版本降级,导致了一个已修复的bug再次出现,该bug与乐观锁机制有关。解决方案是引入Hibernate的特定修复版本。文章还介绍了JPA、SpringDataJPA的基本概念以及它们如何简化数据库操作,包括基于方法名的查询和自定义查询。此外,详细阐述了Hibernate的flush机制和不同flush模式的影响。
382

被折叠的 条评论
为什么被折叠?



