Я использую Spring Boot JPA, с TransactionTemplate и пессимистической блокировкой, я пытаюсь предотвратить обновление записи другим потоком во время транзакции.Вот код:
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, один не имеет ни одного соединения с любой другой таблицей, но имеет «для обновления»
SELECT * FROM ... WHERE ID=? FOR UPDATE
А другой - с соединением, но без «дляupdate "
SLECT * FROM ... left outer join ... left outer join ... where id=?
Надеюсь, это поможет.