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

2022-09-03 02:00:58

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

select * from MY_TABLE where MY_CONDITIONS for update skip locked

我在整个本机查询中运行它,但我必须为所有必需的实体编写该查询。

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

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


答案 1

休眠提供UPGRADE_SKIPLOCKED锁定模式。

使用JPA和Hibernate,要根据Hibernate LockMode文档生成“SKIP_LOCKED”,您必须将PESSIMISTIC_WRITE JPA LockModeType相结合:

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

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

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

(请注意,您也可以为复杂查询配置此锁定模式)

SKIP LOCK 不是 ANSI SQL 的一部分。某些 RDBMS(如下所示)将此作为特定功能提供:

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

  • 没有
  • 乐观的
  • OPTIMISTIC_FORCE_INCREMENT
  • PESSIMISTIC_FORCE_INCREMENT
  • PESSIMISTIC_READ
  • PESSIMISTIC_WRITE

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

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

答案 2

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

由于2.0 JPA允许像这样传递提示

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

推荐