从JPA级别选择更新已跳过锁定

时间:2017-01-02 22:47:31

标签: java oracle jpa locking eclipselink

在我的应用程序 - 带JPA的Oracle(EclipseLink)中,我使用以下表达式来锁定某些表中的记录子集:

select * from MY_TABLE where MY_CONDITIONS for update skip locked

我在原生查询中运行它,但我必须为所有必需的实体编写该查询。

有没有办法使用纯JPA跳过锁定的记录?我可以实施自己的锁定政策吗?

我不介意更改JPA提供程序,但我想使用JPA API。

4 个答案:

答案 0 :(得分:8)

Hibernate提供UPGRADE_SKIPLOCKED锁定模式。

使用JPA和Hibernate,根据Hibernate LockMode文档生成“SKIP_LOCKED”,你必须结合 PESSIMISTIC_WRITE JPA LockModeType

entityManager.find(Department.class, 1, LockModeType.PESSIMISTIC_WRITE);

和锁定超时设置,例如在持久性单元的persistence.xml中:

<properties>
   <property name="javax.persistence.query.timeout" value="-2"/>
</properties>

(请注意,您也可以为复杂查询配置此LockMode)

SKIP LOCKED不是ANSI SQL的一部分。以下一些RDBMS将此作为特定功能提供:

因此,对于纯JPA,无法在查询中指定“SKIP LOCKED”。 实际上,正如LockModeType中所述,JPA 2.1仅支持以下内容:

  • NONE
  • OPTIMISTIC
  • OPTIMISTIC_FORCE_INCREMENT
  • PESSIMISTIC_FORCE_INCREMENT
  • PESSIMISTIC_READ
  • PESSIMISTIC_WRITE
  • READ
  • WRITE

但是,要在查询中启用SKIP LOCKED,您可以使用以下替代方法:

  • 使用特定的JPA实现功能,例如Hibernate LockMode允许通过JPA查询指定SKIP LOCKED,这要归功于 PESSIMISTIC_WRITE LockModeType Lock Timeout特定设置的组合,如上所述< / LI>
  • 像您一样创建本机SQL查询

答案 1 :(得分:2)

我知道这篇文章有些陈旧,但是为了记录起见,正如接受的答案所述,将“ javax.persistence.lock.timeout”设置为“ -2”,而Hibernate会导致“跳过锁定”。但是,这可以在运行时完成,而无需设置任何全局设置。

从2.0 JPA allows to pass hints开始,就像这样

entityManager.find(MyType.class, id, LockModeType.PESSIMISTIC_WRITE, new HashMap<String, Object>() {{
        put("javax.persistence.lock.timeout", "-2");
    }});

答案 2 :(得分:0)

Oracle不提供读锁定,因为它不需要读取锁定;撤消日志使其不必要。因此,SELECT ... FOR UPDATE实际上只是Oracle的WRITE锁。

使用JPA,您希望将LockModeType设置为PESSIMISTIC_WRITE。

答案 3 :(得分:0)

对于spring JpaRepository,可以这样使用:

String SKIP_LOCKED = "-2";
@QueryHints(@QueryHint(name = AvailableSettings.JPA_LOCK_TIMEOUT, value = SKIP_LOCKED))
@Lock(LockModeType.PESSIMISTIC_WRITE)
List<YourEntity> fooBar();

在 Oracle 上运行良好,其他不确定