私のアプリケーションでは、OracleとJPA(EclipseLink)を使用して、次の式を使用して一部のテーブルのレコードのサブセットをロックしています。
select * from MY_TABLE where MY_CONDITIONS for update skip locked
ネイティブクエリ全体で実行しますが、必要なすべてのエンティティに対してそのクエリを作成する必要があります。
純粋なJPAを使用してロックされたレコードをスキップする方法はありますか?独自のロックポリシーを実装できますか?
JPAプロバイダーを変更してもかまいませんが、JPA APIを使用したいと思います。
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は以下のみをサポートしています。
ただし、クエリでSKIP LOCKEDを有効にするには、次の方法を使用できます。
私はこの投稿が少し古いことを知っていますが、記録として、受け入れられた回答が述べたように、「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");
}});
Oracleは読み取りロックを必要としないため、読み取りロックを提供していません。ログを元に戻すと不要になります。したがって、SELECT ... FOR UPDATEは、実際にはOracleの単なる書き込みロックです。
JPAを使用して、LockModeTypeをPESSIMISTIC_WRITEとして設定します。