为何LockModeType.OPTIMISTIC_FORCE_INCREMENT未保存数据仍递增版本?
乐观锁
OPTIMISTIC_FORCE_INCREMENT导致版本两次递增的原因及解释 问题核心
你在银行账户取款实验中,使用带@Version的BankAccount实体,仓库方法通过@Lock(LockModeType.OPTIMISTIC_FORCE_INCREMENT)查询,事务内完成取款逻辑后,发现版本从初始1变为3(查询时1→2,save时2→3),甚至无更新操作时查询也会触发版本递增。
这是预期行为,原因如下
OPTIMISTIC_FORCE_INCREMENT是JPA规范中明确定义的锁模式,它的核心特性就是强制递增版本号,无论事务是否修改了实体:
- 当你在事务中调用带该锁的查询方法时,JPA会标记这个实体,在事务提交时自动更新其版本字段——哪怕你没有修改实体的任何属性,版本号也会被递增。
- 你的业务流程里,事务先执行了带锁查询,事务提交前会先把版本从1改成2;随后执行
save操作(本质是merge),由于实体已被修改(余额变更),JPA会再次触发版本递增,最终版本变为3。
调整建议
如果想让版本只在实际更新时递增一次,适配你的取款场景,可以做以下调整:
- 移除查询方法上的
@Lock(LockModeType.OPTIMISTIC_FORCE_INCREMENT),仅依赖@Version字段实现普通乐观锁:查询账户后直接修改余额,JPA只会在实体属性变更时递增版本,从1→2即可完成预期操作。 - 若需要在查询阶段就锁定版本防止并发修改,可改用
LockModeType.OPTIMISTIC锁——它仅在实体被修改时才递增版本,不会触发无修改的强制版本更新。
内容的提问来源于stack exchange,提问作者Thanyares Permpongpaiboon
相关产品推荐
相关产品推荐

