在JPA中有一种LockMode 是 PESSIMISTIC_INCREMENT, 但从名字上看你会以为这是一种悲观锁策略实现的锁,但事实上在某些情况下,它是借用了version实现了锁。
Query query = entityManager.createQuery("select o from Order o where o.id = 67", Order.class);
query.setLockMode(LockModeType.PESSIMISTIC_FORCE_INCREMENT);
Order order67 = (Order) query.getSingleResult();
如上代码所示, 这种情况下,在发出sql时,便会加上排它锁。这种情况下确实是传统意义上的悲观锁,然后会自动更新version。sql如下
Hibernate: select ... where order0_.id=67 for update
Hibernate: update `order` set version=? where id=? and version=?
但是如果不在查询时指定, 而是通过lock指定锁,你会发现他是通过另一种方式实现了悲观锁策略, 代码如下
Query query = entityManager.createQuery("select o from Order o where o.id = 67", Order.class);
Order order67 = (Order) query.getSingleResult();
entityManager.lock(order67, LockModeType.PESSIMISTIC_FORCE_INCREMENT);
这个片段在lock时,执行一条sql,如下
update `order` set version=? where id=? and version=?
通过update语句将对应order锁住,从而实现了悲观锁策略
具体的PESSIMISTIC_INCREMENT使用场景,这篇文章讲解的很好
另外这里顺带提一句OPTIMISTIC_INCREMENT,这种是乐观锁策略,所以会在事务结束之前,我们自己写在事务中的代码执行之后,执行
update `order` set version=? where id=? and version=?
来实现乐观锁策略,如果更新失败,即version值不匹配,事务回滚。