在HIbernate中的标准中应用UPGRADE锁定时出错

时间:2012-04-13 10:20:17

标签: java hibernate

我正在开发一个使用oracle数据库的应用程序。要与数据库连接,我正在使用Hibernate。我是Hibernate的新手并且遇到了问题所以需要一些帮助。 我的情况是:

  1. 从databaseStatus(我的表中的一列)为'N'<​​/ li>的数据库中选择一些行
  2. 将那些行的ProcessingStatus更新为“U”
  3. 在数据上应用一些逻辑
  4. 将ProcessingStatus更改为'Y'
  5. 我编写了一个代码,如果我将它作为单个进程运行,它将正常工作,但是如果我运行同一个应用程序的多个实例,那么会出现问题,不同的进程可能会选择相同的行进行处理,这是我不想要的。 所以我想锁定由select行返回的所有行,将其ProcessingStatus更新为'U',然后释放锁。 为此,我在Criteria 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那么它可以正常运行,但它会在UPGRADE / WRITE模式下出错。

    引发错误的一段代码是:

    @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;
            }
        }
    }
    

2 个答案:

答案 0 :(得分:0)

在Oracle中使用限制和for update子句存在已知问题,通过Hibernate,至少可以追溯到几年前。见this bug report。尝试取出以下行:

criteria.setMaxResults(count);

再次运行测试。作为旁注,Hibernate中不推荐LockMode.UPGRADE,您应该使用PESSIMISTIC_WRITE

答案 1 :(得分:0)

Oracle不支持limit子句,因此如果Hibernate配置为使用Oracle方言,则无法使用limit子句生成查询。

因此,您需要configure Hibernate使用正确的Oracle方言来使Hibernate为Oracle生成正确的查询。