Не удается получить аннотацию @Lock для метода хранилища для работы с OPTIMISTIC_FORCE_INCREMENT - PullRequest
1 голос
/ 10 мая 2019

Я пытаюсь использовать аннотацию @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

1 Ответ

0 голосов
/ 10 мая 2019

Я отвечаю на свой вопрос, спасибо Йенсу за то, что он указал на оплошность на моей стороне и за разъяснение ожидаемого поведения; может быть, это может быть полезно для других, так как документация не очень ясна по этому вопросу.

Теперь я понимаю, что PESSIMISTIC_FORCE_INCREMENT будет принудительно увеличивать при извлечении объекта, поэтому в пределах транзакции у объекта уже увеличена версия.

С другой стороны, OPTIMISTIC_FORCE_INCREMENT будет увеличивать версию только при фиксации транзакции, поэтому в пределах транзакции у версии еще не увеличена версия.

Я обновил контрольные примеры на github , если это может быть полезно для других.

...