I'm using the Spring Boot JPA, with TransactionTemplate and pessimistic lock, I'm trying to prevent the record from being updated by other thread during the transaction. Here is the code:
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());
});
There is another thread with a while loop, and trying to update the record. Something like below:
while(true){
Entity entity = entity.findOne(id);
repository.save(entity);
System.out.println("save success: " + id)
}
But I have found that the pessimistic lock not work at all, during the print between "start find with lock" and "end find with lock", and also the 2 seconds sleep, I found the entity always can be saved by the other thread. Do I have some misunderstanding with pessimistic lock?
EDIT 1: I have debug and see the sql.
em.find(entityClass, entityId, LockModeType.PESSIMISTIC_WRITE, properties);
has generated two sql, one has none join to any other table, but has "for update"
SELECT * FROM ... WHERE ID=? FOR UPDATE
And the other one is, with join but no "for update"
SLECT * FROM ... left outer join ... left outer join ... where id=?
Hope this can help.