JPA 3 をアノテーション (マッピングファイルなし) とプロバイダー org.hibernate.ejb.HibernatePersistence で使用しています
楽観的な同時実行性が必要です。
1) というタグに頼ってみましたが、うまくいきませんでした。
2)だから私はJavaコードでそれを行うことにしました。次のように、mergeServiceRequest メソッドと Request タイプのオブジェクトがあります。トランザクションを開始し、リクエスト オブジェクトをロックしてから、データベースから Request オブジェクト newRequest を取得し、そのタイムスタンプを現在の 1 つのリクエストと比較します。一致しない場合は、例外をスローします。それらが一致する場合、現在のリクエストを現在の時刻で更新し、enter code here
データベースに保存します。
セッションからトランザクションを開始すると、データベースの行がロックされないため、オブジェクトを手動でロックする必要があります。トランザクションがデータベースのレコードを自動的にロックしないことを示す Java コードをいくつか書きました。
このアプローチの問題はクエリです
Request newRequest=entityManager.createQuery("select r from Request r where serviceRequestId = " + request.getServiceRequestId());
常にリクエストと同じオブジェクトを返します。「リクエスト」はセッションentityMangerにあり、クエリは常にセッションにキャッシュされているものを返します。5 つの query.setHint 行をすべて試しましたが、同じ結果が得られます。データベース クエリは実行されず、結果はセッション キャッシュから直接取得されます。
@Transactional
public void mergeServiceRequest(Request request) {
System.out.println("ServiceRequestDao.java line 209");
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
entityManager.lock(request, LockModeType.WRITE); // use to lock the database row
Query query = entityManager.createQuery("select r from Request r where serviceRequestId = " + request.getServiceRequestId());
//query.setHint("javax.persistence.cache.retrieveMode", "BYPASS");
//query.setHint("org.hibernate.cacheMode", CacheMode.REFRESH);
//query.setHint("javax.persistence.cache.retrieveMode", CacheMode.REFRESH);
//query.setHint("javax.persistence.retrieveMode", CacheMode.REFRESH);
//query.setHint(QueryHints.CACHE_USAGE, CacheUsage.DoNotCheckCache);
Request newRequest=(Request)query.getSingleResult();
if (! newRequest.getLastUpdatedOn().equals(request.getLastUpdatedOn())) {
throw new StaleObjectStateException(request.getClass().toString(), request.getServiceRequestId());
}
request.setLastUpdatedOn(new Date(System.currentTimeMillis()));
entityManager.persist(request);
entityManager.flush();
transaction.commit();
}
3)だから私は別のセッションを使用しようとしましたが、新しいリクエストを取得すると、新しいリクエストはリクエストとは異なります。しかし、何らかの理由で、そうすると、トランザクションがコミットされた後でも、リクエスト オブジェクトのロックが解放されません。コードは以下のようになります
@Transactional
public void mergeServiceRequest(Request request) {
System.out.println("ServiceRequestDao.java line 209");
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
entityManager.lock(request, LockModeType.WRITE); // use to lock the database row
Request newRequest=findRequest(request.getServiceRequestId()); // get it from another session
if (! newRequest.getLastUpdatedOn().equals(request.getLastUpdatedOn())) {
throw new StaleObjectStateException(request.getClass().toString(), request.getServiceRequestId());
}
request.setLastUpdatedOn(new Date(System.currentTimeMillis()));
entityManager.persist(request);
entityManager.flush();
transaction.commit();
//lock on the database record is not released after this, and even after entityManager is closed
}
誰かがこれについて私を助けることができますか?
ありがとう。
ダニエル