0

Oracle データベースを使用するアプリケーションを開発しています。データベースに接続するには、Hibernate を使用しています。Hibernate が初めてで、問題が発生しているため、助けが必要です。私のシナリオは次のとおりです。

  1. processingStatus (私のテーブルの列) が「N」であるデータベースからいくつかの行を選択します</li>
  2. これらの行の ProcessingStatus を「U」に更新します</li>
  3. データにロジックを適用する
  4. ProcessingStatus を「Y」に変更</li>

単一のプロセスとして実行すると正常に動作するコードを書きましたが、同じアプリケーションの複数のインスタンスを実行すると問題が発生し、別のプロセスが処理のために同じ行を取得する可能性があります。したがって、select 行によって返されるすべての行をロックし、ProcessingStatus を 'U' に更新してから、ロックを解除します。これを行うために Criteriacriteria.setLockMode(LockMode.UPGRADE)で API を取得しました。select クエリの実行中にこれを使用して、他の行がこれらの行を選択しないようにする予定ですが、この API を使用しているときにエラーが発生するエラーは次のとおりです。

2602 [main] WARN org.hibernate.util.JDBCExceptionReporter  - SQL Error: -11, SQLState: 37000
2602 [main] WARN org.hibernate.util.JDBCExceptionReporter  - SQL Error: -11, SQLState: 37000
2603 [main] ERROR org.hibernate.util.JDBCExceptionReporter  - Unexpected token: FOR in statement [select this_.CUSTOMER_ID as CUSTOMER1_2_0_, this_.MARKETPLACE_ID as MARKETPL2_2_0_, this_.PROCESSING_DATE as PROCESSING3_2_0_, this_.AMOUNT as AMOUNT2_0_, this_.LAST_SHIP_DATE as LAST5_2_0_, this_.ORDER_DATE as ORDER6_2_0_, this_.PROCESSING_STATUS as PROCESSING7_2_0_, this_.PURCHASE_ID as PURCHASE8_2_0_, this_.QUANTITY as QUANTITY2_0_ from CUSTOMERS_FIRST_ORDER this_ where this_.PROCESSING_DATE=? and this_.MARKETPLACE_ID=? and this_.PROCESSING_STATUS=? limit ? for update]

誰かがこれで私を助けてくれますかLockMode.READ?

エラーをスローするコードは次のとおりです。

@SuppressWarnings("unchecked")
@Transactional
public List<CustomerFirstOrder> getOrders(final Date processingDate, long marketplaceID, int count) throws Exception {
    final Session session = getSession();
    final Criteria criteria = session.createCriteria(CustomerFirstOrder.class);
    criteria.add(Restrictions.eq(PROCESSING_DATE, processingDate));
    criteria.add(Restrictions.eq(MARKETPLACE_ID, marketplaceID));
    criteria.add(Restrictions.eq(PROCESSING_STATUS, ProcessingStatus.NOTPROCESSED.toString().charAt(0)));                ///Select only unprocessed rows
    criteria.setMaxResults(count); // select multiple rows
    criteria.setLockMode(LockMode.UPGRADE);
    LOGGER.debug("selecting multple row for date " + processingDate + " of marketplace " + marketplaceID + " of status " + ProcessingStatus.NOTPROCESSED);
    final List<CustomerFirstOrder> results;
    try {
            results = (List<CustomerFirstOrder>)criteria.list();
            return results;
        }
    }
}
4

2 に答える 2

0

Hibernate を介して Oracle で制限と for update 句を使用することには、少なくとも数年前までさかのぼる既知の問題があります。このバグレポートを参照してください。次の行を取り出してみてください。

criteria.setMaxResults(count);

そして、再びテストを実行します。補足として、LockMode.UPGRADEHibernate では非推奨になっているため、代わりに使用する必要がありますPESSIMISTIC_WRITE

于 2012-04-13T11:15:01.733 に答える
0

Oracle は句をサポートしていないため、Hibernate がOracle ダイアレクトを使用するように構成されている場合limit、Hibernate は句を含むクエリを生成できません。limit

そのため、Hibernateが正しい Oracle ダイアレクトを使用して Oracle の正しいクエリを生成するようにHibernate を構成する必要があります。

于 2012-04-13T11:40:26.670 に答える