我已经阅读了Java Persistence 2.0中的文章Locking and Concurrency,并运行了示例应用程序.但我仍然无法意识到PESSIMISTIC_READ和PESSIMISTIC_WRITE之间的区别.我试图修改代码,并且使用PESSIMISTIC_READ和PESSIMISTIC_WRITE的代码将具有与"for update"调用sql相同的结果.
我使用 Spring Boot、JPA、Oracle 12C 和下面的类型化查询来选择要处理的“新”项目。选择“新”项目后,我会更新其状态,使其不再符合选择条件,但我发现选取相同项目时存在并发问题。
我在这里读到,我需要在查询上设置“LockModeType.PESSIMISTIC_WRITE”,以防止其他线程选择同一行,但它似乎不起作用。
我是否错过了下面的内容,或者我是否需要其他配置来防止并发线程从我的表中检索相同的行?问题是否与锁定级别或实体管理器未更新/刷新有关?
我的@Transactional
服务:
@Override
@Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor=RuntimeException.class)
public MyObject retrieveItemByStatus(StatusEnum status) {
return myRepository.retrieveItemByStatus(status);
}
Run Code Online (Sandbox Code Playgroud)
我的存储库层中的查询:
@Override
public MyObject retrieveItemByStatus(StatusEnum status) {
String sql = "SELECT t FROM myTable t WHERE status = :status ORDER BY id ASC";
try {
TypedQuery<MyObject> query = em.createQuery(sql, MyObject.class).setParameter("status", status);
query.setLockMode(LockModeType.PESSIMISTIC_WRITE);
query.setFirstResult(0);
query.setMaxResults(1);
MyObject myObject = (MyObject) query.getSingleResult();
if (myObject != null) {
myObject.setStatus(StatusEnum.IN_PROGRESS);
MyObject myUpdatedObject = em.merge(myObject);
return myUpdatedObject;
}
} catch (IllegalArgumentException …
Run Code Online (Sandbox Code Playgroud)