2012-04-13 83 views
0

在標準應用升級鎖我開發使用Oracle database.To與我使用Hibernate.I數據庫連接的應用程序是新的Hibernate和卡住的問題,所以需要一些幫助。 我的情況是:錯誤在冬眠

  1. 從數據庫,其processingStatus(在我的表中的列)是「N」
  2. 更新ProcessingStatus對這些行「U」
  3. 選擇一些行應用數據
  4. 一些邏輯
  5. 更改ProcessingStatus爲「Y」

我寫了一個代碼,將正常工作,如果我跑它作爲單一的過程,但會來的問題,如果我運行同一應用程序的多個實例,療法不同的進程可能會選擇相同的行進行處理,我不想要。 所以,我想鎖定所有行,通過選擇行返回更新其ProcessingStatus'U',然後釋放鎖。 爲此我在條件criteria.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; 
     } 
    } 
} 

回答

0

存在已知的問題與使用限制和FOR UPDATE子句中的Oracle,通過Hibernate的,至少可以追溯到幾年。見this bug report。嘗試取出以下行:

criteria.setMaxResults(count); 

並再次運行測試。作爲一個側面說明,LockMode.UPGRADE處於休眠過時,你應該使用PESSIMISTIC_WRITE代替。

+0

我有1點更多的問題,這一鎖定將被釋放? 會不會讓自身釋放時,交易完成或我必須手動解鎖 – Rahul 2012-04-16 07:58:39

+0

你似乎是使用聲明式事務,這意味着休眠時自動管理您的交易爲你在這種情況下它出現在您的交易將結束時的方法回報。不是你想要的,如果我明白你在做什麼。通常情況下,如果您在數據庫上使用悲觀鎖,則可以管理自己的事務。此外,您應該儘快處理這些記錄***並提交結果 - 長時間持有數據庫鎖會延遲應用程序的性能。 – Perception 2012-04-16 10:22:52

0

Oracle不支持limit子句,因此如果配置爲使用Oracle方言,Hibernate無法使用limit子句生成查詢。

所以,你需要configure Hibernate使用正確的Oracle方言來讓Hibernate來生成甲骨文正確的查詢。

+0

當這把鎖將被釋放時,我還有1個問題嗎? 將在交易完成後得到它本身釋放或我必須手動解鎖 – Rahul 2012-04-16 07:57:42

+0

@Rahul:'LockMode.UPGRADE'變成'選擇...的update'鎖定人提供在事務結束時釋放。 – axtavt 2012-04-16 08:24:20