web-dev-qa-db-ja.com

JPAレベルから更新スキップをロックするために選択

私のアプリケーションでは、OracleとJPA(EclipseLink)を使用して、次の式を使用して一部のテーブルのレコードのサブセットをロックしています。

select * from MY_TABLE where MY_CONDITIONS for update skip locked

ネイティブクエリ全体で実行しますが、必要なすべてのエンティティに対してそのクエリを作成する必要があります。

純粋なJPAを使用してロックされたレコードをスキップする方法はありますか?独自のロックポリシーを実装できますか?

JPAプロバイダーを変更してもかまいませんが、JPA APIを使用したいと思います。

13
Dominik Kunicki

HibernateはUPGRADE_SKIPLOCKEDロックモードを提供します。

JPAとHibernateを使用して Hibernate LockMode のドキュメントに従って「SKIP_LOCKED」を生成するには、PESSIMISTIC_WRITEJPA 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では、クエリで「スキップロック」を指定することはできません。実際、 LockModeType に記載されているように、JPA 2.1は以下のみをサポートしています。

  • NONE
  • 楽観的
  • OPTIMISTIC_FORCE_INCREMENT
  • PESSIMISTIC_FORCE_INCREMENT
  • PESSIMISTIC_READ
  • PESSIMISTIC_WRITE
  • 読んだ
  • 書く

ただし、クエリでSKIP LOCKEDを有効にするには、次の方法を使用できます。

  • Hibernate LockMode などの特定のJPA実装機能を使用しますPESSIMISTIC_WRITELockModeType Lock Timeoutの組み合わせにより、JPAクエリを介してSKIP LOCKEDを指定できます。上記の特定の設定
  • 作成したようにネイティブSQLクエリを作成する
8
Rémi Bantos

私はこの投稿が少し古いことを知っていますが、記録として、受け入れられた回答が述べたように、「javax.persistence.lock.timeout」が「-2」に設定され、Hibernateは「SKIP LOCKED」になります。ただし、これは実行時にグローバル設定を行うことなく実行できます。

2.0 JPA以降 ヒントを渡すことができます そのまま

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

Oracleは読み取りロックを必要としないため、読み取りロックを提供していません。ログを元に戻すと不要になります。したがって、SELECT ... FOR UPDATEは、実際にはOracleの単なる書き込みロックです。

JPAを使用して、LockModeTypeをPESSIMISTIC_WRITEとして設定します。

0
gregory