2012-04-13 81 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