SpringData1.6以降の場合
@Lock
Spring Data JPAのバージョン1.6以降のCRUDメソッドでサポートされています(実際、マイルストーン
利用可能)。この
そのバージョンでは、次のことを宣言するだけです。
interface WidgetRepository extends Repository<Widget, Long> {
@Lock(LockModeType.PESSIMISTIC_WRITE)
Widget findOne(Long id);
}
これにより、バッキングリポジトリプロキシのCRUD実装部分が、構成されたLockModeTypeをfind(…)
に適用します。 EntityManager
を呼び出す 。
一方、
以前のバージョンのSpringData1.6の場合
春のデータ悲観的な@Lock
アノテーションは(ご指摘のとおり)クエリにのみ適用されます。トランザクション全体に影響を与える可能性があると私が知っている注釈はありません。 findByOnePessimistic
を作成することができます findByOne
を呼び出すメソッド 悲観的なロックを使用するか、findByOne
を変更できます 常に悲観的なロックを取得します。
独自のソリューションを実装したい場合は、おそらく可能です。内部では、@Lock
アノテーションはLockModePopulatingMethodIntercceptor
によって処理されます これは次のことを行います:
TransactionSynchronizationManager.bindResource(method, lockMode == null ? NULL : lockMode);
ThreadLocal<LockMode>
を持つ静的ロックマネージャーを作成できます。 メンバー変数を作成し、ThreadLocalで設定されたロックモードでbindResourceを呼び出したすべてのリポジトリのすべてのメソッドにアスペクトをラップします。これにより、スレッドごとにロックモードを設定できます。次に、独自の@MethodLockMode
を作成できます。 メソッドを実行する前にスレッド固有のロックモードを設定し、メソッドの実行後にそれをクリアするアスペクトでメソッドをラップするアノテーション。
リソースリンク:
- Spring Data JPAでエンティティを検索するときにLockModeType.PESSIMISTIC_WRITEを有効にするにはどうすればよいですか?
- カスタムを追加する方法SpringDataJPAの方法
- PostgresでのSpringDataPessimisticLockタイムアウト
- JPAクエリAPI
ペシミスティックロックタイムアウトのさまざまな例
ペシミスティックロックの設定
エンティティオブジェクトは、lockメソッドによって明示的にロックできます:
em.lock(employee, LockModeType.PESSIMISTIC_WRITE);
最初の引数はエンティティオブジェクトです。 2番目の引数は要求されたロックモードです。
TransactionRequiredException
明示的なロックにはアクティブなトランザクションが必要なため、ロックが呼び出されたときにアクティブなトランザクションがない場合にスローされます。
LockTimeoutException
要求されたペシミスティックロックを付与できない場合にスローされます:
-
PESSIMISTIC_READ
別のユーザー(別のEntityManagerインスタンスによって表される)が現在PESSIMISTIC_WRITE
を保持している場合、ロック要求は失敗します そのデータベースオブジェクトをロックします。 -
PESSIMISTIC_WRITE
別のユーザーが現在PESSIMISTIC_WRITE
のいずれかを保持している場合、ロック要求は失敗します ロックまたはPESSIMISTIC_READ
そのデータベースオブジェクトをロックします。
クエリヒント(スコープ)の設定
クエリヒントは、次のスコープ(グローバルからローカルまで)で設定できます:
永続性ユニット全体の場合-persistence.xml
を使用 プロパティ:
<properties>
<property name="javax.persistence.query.timeout" value="3000"/>
</properties>
EntityManagerFactoryの場合-createEntityManagerFacotory
を使用 方法:
Map<String,Object> properties = new HashMap();
properties.put("javax.persistence.query.timeout", 4000);
EntityManagerFactory emf =
Persistence.createEntityManagerFactory("pu", properties);
EntityManagerの場合-createEntityManager
を使用 方法:
Map<String,Object> properties = new HashMap();
properties.put("javax.persistence.query.timeout", 5000);
EntityManager em = emf.createEntityManager(properties);
またはsetPropertyメソッドを使用します:
em.setProperty("javax.persistence.query.timeout", 6000);
named query
の場合 定義-hints
を使用 要素:
@NamedQuery(name="Country.findAll", query="SELECT c FROM Country c",
hints={@QueryHint(name="javax.persistence.query.timeout", value="7000")})
特定のクエリ実行の場合-setHint
を使用 メソッド(クエリ実行前):
query.setHint("javax.persistence.query.timeout", 8000);