1

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
    }

誰かがこれについて私を助けることができますか?

ありがとう。

ダニエル

4

0 に答える 0