Select 用于从 JPA 级别锁定的更新跳过

Select for update skip locked from JPA level

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

select * from MY_TABLE where MY_CONDITIONS for update skip locked

我 运行 它贯穿本机查询,但我必须为所有必需的实体编写该查询。

有什么方法可以使用纯 JPA 跳过锁定的记录吗?我可以实施自己的锁定策略吗?

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

Oracle 不提供读锁,因为它不需要;撤消日志使它变得不必要。所以,SELECT...FOR UPDATE 实际上只是 Oracle 的 WRITE 锁。

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

Hibernate 提供 UPGRADE_SKIPLOCKED 锁定模式。

使用 JPA 和 Hibernate,根据 Hibernate LockMode documentation, you have to combine the PESSIMISTIC_WRITE JPA LockModeType:

生成 "SKIP_LOCKED"
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_FORCE_INCREMENT
  • PESSIMISTIC_FORCE_INCREMENT
  • PESSIMISTIC_READ
  • PESSIMISTIC_WRITE
  • 阅读
  • 写入

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

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

我知道这个 post 有点旧,但是为了记录,正如接受的答案所述,"javax.persistence.lock.timeout" (org.hibernate.cfg.AvailableSettings#JPA_LOCK_TIMEOUT) 设置为“-2”(org.hibernate.LockOptions#SKIP_LOCKED) 与 Hibernate 结果 "SKIP LOCKED"。但是,这可以在 运行 时完成,而无需设置任何全局设置。

从 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");
    }});

对于springJpaRepository,可以这样使用:

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

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