Я пытаюсь использовать аннотацию @Lock в репозитории Spring Jpa, устанавливая режим блокировки на OPTIMISTIC_FORCE_INCREMENT, но версия не увеличивается.
Тот же тест, использующий EntityManager.find () и указывающий режим блокировки, работает нормально.
Тот же самый контрольный пример с использованием PESSIMISTIC_FORCE_INCREMENT также работает нормально.
Интересно, я что-то упускаю, или я бью какое-то недокументированное ограничение или просто ошибку.
Моя среда:
Java 11 на Windows 10
Spring Boot 2.1.3.RELEASE со связанными компонентами Spring (такими как SPring Data Jpa) согласно спецификации Spring Boot.
Hibernate 5.3.7.Final
H2 1.4.199 [но я тестировал с MariaDB, получая те же результаты]
Сущность:
@Entity
@Access(AccessType.FIELD)
public class Parent {
@Id private Long id;
@Version private Long version;
private String desc;
... getters, setters, hashcode and equals
}
Хранилище ...
public interface ParentRepository extends JpaRepository<Parent, Long> {
@Lock(LockModeType.OPTIMISTIC_FORCE_INCREMENT)
Optional<Parent> findById(Long id);
@Lock(LockModeType.OPTIMISTIC_FORCE_INCREMENT)
@Query("select p from Parent p where p.id = ?1")
Optional<Parent> optimisticFindById(Long id);
@Lock(LockModeType.PESSIMISTIC_FORCE_INCREMENT)
@Query("select p from Parent p where p.id = ?1")
Optional<Parent> pessimisticFindById(Long id);
}
Тестовый пример с использованием EntityManager.find (),
версия увеличивается при поиске сущности
public void forceIncrementWithEmTest() {
// set the id
Long id = 275L;
// build the entity
Parent p0 = new Parent(id, "Hello world.");
assertThat(p0.getVersion(), is(nullValue()));
// persist it
em.persist(p0);
em.flush();
// Version is 0L as expected
assertThat(p0.getVersion(), is(0L));
// clear the persistence context
em.clear();
// get the object again from DB, requiring the lock
Parent p1 = em.find(
Parent.class,
id,
LockModeType.PESSIMISTIC_FORCE_INCREMENT);
assertThat(p1, notNullValue());
// version has been incremented as expected
assertThat(p1.getVersion(), is(1L));
// flush and clear the context
em.flush();
em.clear();
// get from DB without locks
Parent p2 = em.find(Parent.class, id);
assertThat(p2, notNullValue());
// version has not been incremented this time, as expected
assertThat(p2.getVersion(), is(1L));
}
Тестовый пример с использованием повторно объявленного метода репозитория findById
версия не увеличивается, как я ожидал
@Test
@Transactional
public void forceIncrementWithRepoQueryOptimisticTest() {
// set the id
Long id = 275L;
// build the entity
Parent p0 = new Parent(id, "Hello world.");
assertThat(p0.getVersion(), is(nullValue()));
// persist it
em.persist(p0);
em.flush();
// Version is 0 as expected
assertThat(p0.getVersion(), is(0L));
// clear the persistence context
em.clear();
// get the object again from DB, requiring the lock
// this time using the repository with the @Lock annotation
// and a custom query
Optional<Parent> popt = parentRepo.optimisticFindById(id);
assertThat(popt.isPresent(), is(true));
Parent p1 = popt.get();
// I expected version to have been incremented, but instead it is still 0L
// so the @Lock annotation has had no effect
assertThat(p1.getVersion(), is(0L));
Parent p2 = parentRepo.saveAndFlush(p1);
// also the saved entity still has version not incremented
// as if the @Lock annotation was not considered.
assertThat(p2.getVersion(), is(0L));
}
Я получаю то же поведение с пользовательским методом с аннотацией @Query.
Подстановка OPTIMISTIC_FORCE_INCREMENT в PESSIMISTIC_FORCE_INCREMENT Я получаю ожидаемое поведение во всех случаях.
Полная настройка и тестовые случаи доступны на https://github.com/gpaglia/spring-lock-problem.git