PESSIMISTIC_INCREMENT 实际并不使用 pessimistic lock strategy

本文详细解析了JPA中PESSIMISTIC_INCREMENT锁模式的工作原理及其实现方式,并对比了OPTIMISTIC_INCREMENT乐观锁策略。

在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值不匹配,事务回滚。

### `@Lock(LockModeType.PESSIMISTIC_WRITE)` 在数据库操作中的使用 `@Lock(LockModeType.PESSIMISTIC_WRITE)` 是 JPA(Java Persistence API) 中用于悲观锁的注解。在 JPA 中,当需要对数据库中的数据进行操作时,为了保证数据的一致性和完整性,避免多个事务同时修改同一数据导致的数据冲突问题,可以使用悲观锁机制。`@Lock(LockModeType.PESSIMISTIC_WRITE)` 就是悲观锁的一种实现方式,它表示在查询数据时,会对查询到的记录添加写锁,防止其他事务对这些记录进行修改,直到当前事务结束。 以下是一个简单的使用示例: ```java import javax.persistence.EntityManager; import javax.persistence.LockModeType; import javax.persistence.PersistenceContext; import org.springframework.stereotype.Repository; @Repository public class IdTableRepository { @PersistenceContext private EntityManager entityManager; public IdTable findByIdTypeWithPessimisticWrite(String idType) { return entityManager.find(IdTable.class, idType, LockModeType.PESSIMISTIC_WRITE); } } ``` 在上述示例中,`findByIdTypeWithPessimisticWrite` 方法使用了 `@Lock(LockModeType.PESSIMISTIC_WRITE)` 注解(这里通过 `LockModeType.PESSIMISTIC_WRITE` 参数体现),当调用该方法查询 `IdTable` 实体时,会对查询到的记录添加写锁。 ### 与 `SELECT max_id FROM id_table WHERE id_type = 'ORDER' FOR UPDATE` 的关联 `SELECT max_id FROM id_table WHERE id_type = 'ORDER' FOR UPDATE` 是 SQL 层面的悲观锁语句,用于在查询符合条件的记录时,对这些记录添加排他锁,防止其他事务对这些记录进行修改。而 `@Lock(LockModeType.PESSIMISTIC_WRITE)` 是 JPA 层面的悲观锁注解,它们的目的是相同的,都是为了在并发环境下保证数据的一致性和完整性。 当使用 JPA 进行数据库操作时,如果需要实现与 `SELECT max_id FROM id_table WHERE id_type = 'ORDER' FOR UPDATE` 相同的功能,可以使用 `@Lock(LockModeType.PESSIMISTIC_WRITE)` 注解。例如: ```java import javax.persistence.EntityManager; import javax.persistence.LockModeType; import javax.persistence.PersistenceContext; import javax.persistence.Query; import org.springframework.stereotype.Repository; @Repository public class IdTableRepository { @PersistenceContext private EntityManager entityManager; public Integer getMaxIdForOrder() { String jpql = "SELECT maxId FROM IdTable WHERE idType = :idType"; Query query = entityManager.createQuery(jpql); query.setParameter("idType", "ORDER"); query.setLockMode(LockModeType.PESSIMISTIC_WRITE); return (Integer) query.getSingleResult(); } } ``` 在上述示例中,`getMaxIdForOrder` 方法使用 JPA 的 `Query` 对象执行 JPQL 查询,并通过 `setLockMode(LockModeType.PESSIMISTIC_WRITE)` 方法对查询结果添加写锁,其效果与 `SELECT max_id FROM id_table WHERE id_type = 'ORDER' FOR UPDATE` 类似。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值