首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无法在存储库方法上获取@Lock批注以使用OPTIMISTIC_FORCE_INCREMENT

无法在存储库方法上获取@Lock批注以使用OPTIMISTIC_FORCE_INCREMENT
EN

Stack Overflow用户
提问于 2019-05-10 05:26:41
回答 1查看 786关注 0票数 1

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

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

我想知道我是否遗漏了什么,或者我遇到了一些未记录的限制,或者只是一个bug。

我的环境:根据Spring Boot BOM,在Windows10Spring Boot2.1.3.RELEASE上安装相关的Spring组件(比如SPring Data Jpa)。Hibernate 5.3.7最终的H2 1.4.199,但我已经用MariaDB进行了测试,得到了相同的结果

实体:

代码语言:javascript
复制
@Entity
@Access(AccessType.FIELD)
public class Parent {
@Id private Long id;
@Version private Long version;
private String desc;
... getters, setters, hashcode and equals
}

仓库..。

代码语言:javascript
复制
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()的测试用例,版本在检索实体时递增

代码语言:javascript
复制
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存储库方法的测试用例版本不会像我预期的那样递增

代码语言:javascript
复制
  @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注释的自定义方法获得了相同的行为。

用PESSIMISTIC_FORCE_INCREMENT替换OPTIMISTIC_FORCE_INCREMENT,我得到了所有情况下的预期行为。

完整的设置和测试案例可在https://github.com/gpaglia/spring-lock-problem.git上找到

EN

回答 1

Stack Overflow用户

发布于 2019-05-10 18:46:39

我回答了我自己的问题,感谢Jens指出了我这方面的疏忽,并澄清了预期的行为;也许这对其他人有用,因为文档在这一点上不是很清楚。

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

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

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56067813

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档