我试图在Spring Jpa存储库上使用@Lock注释,将锁定模式设置为OPTIMIZE\u FORCE\u INCREMENT,但版本没有增加。
使用EntityManager.find()并指定锁定模式的相同测试用例工作正常。使用PESSIMISTIC_FORCE_INCREMENT的相同测试用例也工作正常。
我想知道我是否遗漏了什么,或者我遇到了一些未记录的限制,或者只是一个bug。
我的环境:Windows 10 Spring Boot 2.1.3上的Java 11。根据Spring Boot BOM,使用相关Spring组件(如Spring Data Jpa)发布。Hibernate5.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
我回答了自己的问题,感谢Jens指出了我的疏忽,并澄清了预期的行为;也许这对其他人有用,因为文档在这一点上不是很清楚。
我现在明白PESSIMISTIC_FORCE_INCREMENT将在获取实体时强制递增,因此,在事务边界内,实体的版本已经递增。
另一方面,OPTIMIZE\u FORCE\u INCREMENT将仅在事务提交时增加版本,因此,在事务边界内,实体的版本尚未增加。
如果这对其他人有用,我更新了github上的测试用例。
问题内容: 有人可以给MWE 直接在方法上使用注释的方法吗? 我已经看到了无数的关于在类定义中使用它的示例-但还没有方法的示例。 引用文档: 这种添加到一个类定义或 一个方法 @Target(value = {TYPE, METHOD }) 因此,我认为还有一种可能性和预期的用途-但不幸的是,我无法弄清楚。 问题答案: 这里的DataSource类具有属性url,用户名,密码,driverClas
我希望获得、和。以下是我现在所拥有的:
使用laravel 7/livewire应用程序,我使用Repository制作crud,并获得了数据列表,在装载事件中,我分配了受保护的var$FacilityRepository,它在render方法中正常工作, 但在编辑方法中为空,我得到错误: 当用户单击“编辑链接”时 在模板中,编辑链接定义为: 为什么会出现错误以及如何修复? 修改#2: > 类设施扩展组件{...公共$FacilityR
我正在我的应用程序中嵌入用于推送通知的GCM。我面临一个非常奇怪的问题,第一次运行时我无法获得GCM注册令牌,但当你第二次运行我的应用程序时,你将在控制台上打印注册ID。我不知道我在干什么。以下是我迄今为止所做的工作。 这是我的onCreate()方法,我想在其中打印GCM注册表: 执行以下代码: 通过以下方法将GCM_regId发送到服务器,如本教程所示: 我不这么认为,这里需要gcminent
这个问题来自于,如果我有一个methodA和methodB在classA中,如下所示 但是,如果我在中确实有很多工作要做,那么spring会在整个执行时间内锁定表吗?
Eclipse for Testers版本:Indigo Release Build ID:20110615-0604 “无法读取http://beust.com/eclipse上得存储库.http://beust.com/eclipse不是有效得存储库位置.”