我正尝试在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进行了测试,得到了相同的结果
实体:
@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注释的自定义方法获得了相同的行为。
用PESSIMISTIC_FORCE_INCREMENT替换OPTIMISTIC_FORCE_INCREMENT,我得到了所有情况下的预期行为。
完整的设置和测试案例可在https://github.com/gpaglia/spring-lock-problem.git上找到
https://stackoverflow.com/questions/56067813
复制相似问题