能否使用Optimistic Lock仅通过2条SQL完成Person实体更新?
解决方案:去掉@Lock注解,仅靠@Version实现乐观锁即可
完全可以做到只用2条SQL完成更新,同时保留乐观锁的安全性,具体调整和原因如下:
为什么会出现额外的version查询:你给
findById加的@Lock(LockModeType.OPTIMISTIC)是冗余的,部分JPA实现(比如Hibernate)会因为这个注解,在事务提交前额外发起一次version查询做验证,这就多了一条SQL。去掉@Lock后不会影响安全性:你的实体类已经标注了
@Version字段,JPA默认就会基于这个字段实现完整的乐观锁逻辑:- 调用
findById时,SQL会加载包括version在内的所有实体字段; - 修改实体后,事务提交时生成的update语句会自动带上
version作为where条件(比如update person set name=?, version=? where id=? and version=?); - 如果并发修改导致数据库中的version和加载的不一致,update语句会返回0行受影响,JPA会自动抛出
OptimisticLockingFailureException,和加@Lock(OPTIMISTIC)的效果完全一致。
- 调用
调整后的仓库接口代码:
public interface PersonRepository extends JpaRepository<Person, Integer> { // 去掉@Lock注解,保留默认的findById即可 Optional<Person> findById(int id); }
调整后执行更新操作只会生成两条SQL:
- 加载实体的查询:
select id, name, age, version from person where id=? - 带乐观锁验证的更新:
update person set name=?, version=? where id=? and version=?
内容的提问来源于stack exchange,提问作者olivernick89
相关产品推荐
相关产品推荐

