我正在使用带有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=?
希望这会有所帮助。
答案 0 :(得分:0)
是的,如果您将Hibernate用作JPA实现,则尚不支持它。因此锁不会扩展到联接
JPA标准所指定的javax.persistence.lock.scope尚不支持。