Java 在HIbernate中应用升级锁定条件时出错
我正在开发一个使用oracle数据库的应用程序。要连接数据库,我正在使用Hibernate。我刚接触Hibernate,遇到了一个问题,需要一些帮助。 我的设想是:Java 在HIbernate中应用升级锁定条件时出错,java,hibernate,Java,Hibernate,我正在开发一个使用oracle数据库的应用程序。要连接数据库,我正在使用Hibernate。我刚接触Hibernate,遇到了一个问题,需要一些帮助。 我的设想是: 从processingStatus(我表中的一列)为“N”的数据库中选择一些行 将这些行的ProcessingStatus更新为“U” 对数据应用一些逻辑 将ProcessingStatus更改为“Y” 我写了一个代码,如果我把它作为一个进程运行,它会工作得很好,但如果我运行同一个应用程序的多个实例,问题就会出现,不同的进程可能会选
Criteria.setLockMode(LockMode.UPGRADE)
中获得了一个API,我计划在运行select查询时使用该API,以便任何其他行都不会选择这些行,但问题是,当我使用此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;
}
}
}
@SuppressWarnings(“未选中”)
@交易的
公共列表getOrders(final Date processingDate、long marketplaceID、int count)引发异常{
最终会话=getSession();
最终标准=session.createCriteria(CustomerFirstOrder.class);
标准.添加(限制.eq(处理日期,处理日期));
标准.添加(限制.eq(市场ID,marketplaceID));
criteria.add(Restrictions.eq(PROCESSING_STATUS,ProcessingStatus.NOTPROCESSED.toString().charAt(0));///仅选择未处理的行
criteria.setMaxResults(count);//选择多行
标准。设置锁定模式(锁定模式。升级);
LOGGER.debug(“为日期“+processingDate+”市场“+marketplaceID+”状态“+ProcessingStatus.NOTPROCESSED”选择多行);
最终结果清单;
试一试{
results=(List)criteria.List();
返回结果;
}
}
}
在Oracle中,通过Hibernate使用limits和for update子句存在一些已知问题,这些问题至少可以追溯到几年前。看见尝试取出以下行:
criteria.setMaxResults(count);
然后再次运行测试。作为旁注,
LockMode.UPGRADE
在Hibernate中是不推荐的,您应该使用悲观写入
。Oracle不支持limit
子句,因此如果Hibernate配置为使用Oracle方言,则无法使用limit
子句生成查询
因此,您需要使用正确的Oracle方言,使Hibernate为Oracle生成正确的查询。我还有一个问题,即何时释放此锁?当交易完成时,它会自动释放还是我必须手动解锁it@Rahul:
锁定模式。升级
变成选择。。。对于事务结束时释放的更新
锁。我还有一个问题:何时释放此锁?当事务完成时,它会自动释放吗?或者我必须手动解锁它。您似乎正在使用声明性事务,这意味着Hibernate将自动为您管理事务,在这种情况下,当方法返回时,您的事务将结束。如果我明白你在做什么,那就不是你想要的。通常,如果在数据库上使用悲观锁,则可以管理自己的事务。此外,您应该尝试快速处理这些记录并提交结果——长时间持有DB锁会延迟应用程序的性能。