在事务中使用悲观锁定不能阻止记录被更新吗?

时间:2019-02-23 10:17:18

标签: spring-boot jpa pessimistic-locking

我正在使用带有TransactionTemplate和悲观锁的Spring Boot JPA,我试图防止记录在事务期间被其他线程更新。这是代码:

    transactionService.executeTransaction(() -> {
        Map<String, Object> properties = new HashMap<>();
        properties.put("javax.persistence.lock.scope", PessimisticLockScope.EXTENDED);
        System.out.println("--------------------- start find with lock, job id: " + entityId);
        Entity newEntity = (Entity) em.find(entityClass, entityId, LockModeType.PESSIMISTIC_WRITE, properties);
        System.out.println("+++++++++++++++++++++ end find with lock, job id: " + entityId);
        try{
            Thread.sleep(2000);
        }catch (InterruptedException e){

        }
        newEntity = setEntity.setEntity(newEntity);
        System.out.println(Thread.currentThread().getName() + ": use transaction to save: " + newEntity.getId());
    });

还有一个带有while循环的线程,并试图更新记录。如下所示:

while(true){
    Entity entity = entity.findOne(id);
    repository.save(entity);
    System.out.println("save success: " + id)
}

但是我发现悲观锁根本不起作用,在“开始用锁开始查找”和“结束用锁结束查找”之间打印以及还有2秒钟的睡眠期间,我发现该实体始终可以通过以下方式保存另一个线程。我对悲观锁有误解吗?

编辑1: 我已经调试并看到了sql。

em.find(entityClass, entityId, LockModeType.PESSIMISTIC_WRITE, properties);

已生成两个sql,一个sql没有连接到任何其他表,但是具有“ for update”

SELECT * FROM ... WHERE ID=? FOR UPDATE

另一个是,有连接但没有“用于更新”的

SLECT * FROM ... left outer join ... left outer join ... where id=? 

希望这会有所帮助。

1 个答案:

答案 0 :(得分:0)

是的,如果您将Hibernate用作JPA实现,则尚不支持它。因此锁不会扩展到联接

  

JPA标准所指定的javax.persistence.lock.scope尚不支持。

来自Hibernate Docs

Related Ticket