无法在存储库方法上获取@Lock注释以与OPTIMISTIC_FORCE_INCREMENT一起使用

时间:2019-05-09 21:26:41

标签: hibernate spring-data-jpa locking

我正在尝试在Spring Jpa存储库上使用@Lock批注,将锁定模式设置为OPTIMISTIC_FORCE_INCREMENT,但是版本未递增。

使用EntityManager.find()并指定锁定模式的相同测试用例可以正常工作。 使用PESSIMISTIC_FORCE_INCREMENT的相同测试案例也可以正常工作。

我想知道我是否缺少某些东西,还是遇到了一些未记录的限制,或者仅仅是一个错误。

我的环境: Windows 10上的Java 11 Spring Boot 2.1.3.RELEASE具有与Spring Boot BOM相关的相关Spring组件(例如SPring Data Jpa)。 休眠5.3.7。最终版 H2 1.4.199 [但是我已经对MariaDB进行了测试,得到了相同的结果]

实体:

newBaseRef.set

存储库...

@Entity
@Access(AccessType.FIELD)
public class Parent {
@Id private Long id;
@Version private Long version;
private String desc;
... getters, setters, hashcode and equals
}

使用EntityManager.find()的测试用例, 实体检索时版本会增加

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);

}

使用重新声明的findById存储库方法的测试用例 版本未按我预期的那样

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));

  }

使用带有@Query注释的自定义方法,我会得到相同的行为。

用PESSIMISTIC_FORCE_INCREMENT代替OPTIMISTIC_FORCE_INCREMENT我在所有情况下都得到了预期的行为。

有关完整的设置和测试案例,请访问https://github.com/gpaglia/spring-lock-problem.git

1 个答案:

答案 0 :(得分:0)

由于Jens指出了我这一方面的疏忽并澄清了预期的行为,我回答了我自己的问题;也许这对其他人可能有用,因为此时文档尚不十分清楚。

我现在了解到PESSIMISTIC_FORCE_INCREMENT将在获取实体时强制增加,因此,在事务边界内,实体的版本已经增加。

另一方面,OPTIMISTIC_FORCE_INCREMENT仅在提交事务时才增加版本,因此,在事务边界内,实体的版本尚未增加。

如果这对其他人有用,我在github上更新了测试用例。