Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/svg/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oracle JPA悲观锁不工作_Oracle_Hibernate_Jpa_Transactions_Locking - Fatal编程技术网

Oracle JPA悲观锁不工作

Oracle JPA悲观锁不工作,oracle,hibernate,jpa,transactions,locking,Oracle,Hibernate,Jpa,Transactions,Locking,我正在使用SpringBoot、JPA、Oracle12C和下面的键入查询来选择要处理的“新”项目。一旦我选择了一个“新”项目,我会更新它的状态,这样它就不再有资格被选择了,但是我看到了一个相同项目被选中的并发问题 我读到我需要在查询上设置一个“LockModeType.悲观_WRITE”,以防止其他线程选择同一行,但它似乎不起作用 我是否遗漏了下面的内容,或者我是否需要另一种配置来防止并发线程从表中检索相同的行?问题是与锁定级别有关还是与实体管理器未得到更新/刷新有关 我的@事务性服务: @O

我正在使用SpringBoot、JPA、Oracle12C和下面的键入查询来选择要处理的“新”项目。一旦我选择了一个“新”项目,我会更新它的状态,这样它就不再有资格被选择了,但是我看到了一个相同项目被选中的并发问题

我读到我需要在查询上设置一个“LockModeType.悲观_WRITE”,以防止其他线程选择同一行,但它似乎不起作用

我是否遗漏了下面的内容,或者我是否需要另一种配置来防止并发线程从表中检索相同的行?问题是与锁定级别有关还是与实体管理器未得到更新/刷新有关

我的
@事务性
服务:

@Override
@Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor=RuntimeException.class)
public MyObject retrieveItemByStatus(StatusEnum status) {
    return myRepository.retrieveItemByStatus(status);
}
“我的存储库”层中的查询:

@Override
public MyObject retrieveItemByStatus(StatusEnum status) {

    String sql = "SELECT t FROM myTable t WHERE status = :status ORDER BY id ASC";      
    try {
        TypedQuery<MyObject> query = em.createQuery(sql, MyObject.class).setParameter("status", status);
        query.setLockMode(LockModeType.PESSIMISTIC_WRITE);
        query.setFirstResult(0);
        query.setMaxResults(1);
        MyObject myObject = (MyObject) query.getSingleResult();
        if (myObject != null) {
            myObject.setStatus(StatusEnum.IN_PROGRESS);
            MyObject myUpdatedObject = em.merge(myObject);                              
            return myUpdatedObject;
        }
    } catch (IllegalArgumentException iae) {
        //some logging
    } catch(NoResultException nrf) {            
        //some logging
    } catch(Exception ex) {
        //some logging
    }       
    return null;
}
@覆盖
公共MyObject retrieveItemByStatus(状态枚举状态){
String sql=“从myTable t中选择t,其中状态=:按id ASC排序的状态”;
试一试{
TypedQuery query=em.createQuery(sql,MyObject.class).setParameter(“状态”,status);
setLockMode(LockModeType.悲观_WRITE);
query.setFirstResult(0);
query.setMaxResults(1);
MyObject MyObject=(MyObject)query.getSingleResult();
if(myObject!=null){
myObject.setStatus(状态枚举进行中);
MyObject MyUpdateObject=em.merge(MyObject);
返回MyUpdateObject;
}
}捕获(IllegalArgumentException iae){
//一些伐木
}捕获(NoResultException nrf){
//一些伐木
}捕获(例外情况除外){
//一些伐木
}       
返回null;
}

如果您无法阻止oracle中的“读取”。。。悲观锁对应于不阻止其他
select
语句的
select for update
。。。它只强制它读取数据的旧版本(在
选择更新之前)
运行)。。。它将只阻止其他
select for update
语句(因此其他查询具有悲观锁)

我可以确认这一观察结果。我用H2数据库测试了几种锁模式,所有这些都按预期工作。与Oracle数据库结合使用时,两种悲观锁模式都不能正常工作。因此,问题是:这个代码有什么问题

对于Oracle,其中两个并发代码执行会产生相同的数据,尽管第一个会阻止第二个:

// Every Thread gets its own Hibernate session:
final Session session = HibernateSessionHolder.get();

session.getTransaction().begin();
final List<EventDeliveryDataDB> eddList = 
        session.createCriteria(EventDeliveryDataDB.class)
            .setLockMode(LockMode.PESSIMISTIC_WRITE) // with READ the same
            .add(eq("progress", NEW))
            .list();
eddList.stream().forEach(eddElem -> eddElem.setProgress(IN_PROGRESS));
session.getTransaction().commit();

感谢您的回复,更新我的查询要使用什么解决方案
select for update
。。。您现在谈论的是另一个能够读取数据的查询,但您不希望它这样做。。。对吗?如果是这样的话。。我认为这取决于您的业务和实施。。。它是。需要锁定它吗?多久打一次电话?这将如何影响性能?有没有死锁的机会?是否允许业务智能阻止此查询?我指的是另一个线程试图使用上述查询同时更新同一行。我在云环境中运行应用程序,当我将状态从
NEW
更新为
in_progress
时,需要锁定行,这样其他线程就不能同时读/写同一行。附加说明:我希望第二次调用在尝试执行“选择更新和更新”并提交它们。这是H2数据库的行为示例。有关于此问题的更新吗?您是否能够解决此问题或解决此问题?
Hibernate: select this_.DD_ID as DD_ID1_2_0_, this_.CHANNEL_NAME as CHANNEL_NAME2_2_0_, this_.created as created3_2_0_, this_.DELIVERY_TIME as DELIVERY_TIME4_2_0_, this_.ERROR_CODE as ERROR_CODE5_2_0_, this_.ERROR_MESSAGE as ERROR_MESSAGE6_2_0_, this_.EVENT_ID as EVENT_ID7_2_0_, this_.MAX_RETRIES as MAX_RETRIES8_2_0_, this_.PROGRESS as PROGRESS9_2_0_, this_.PROGRESS_ID as PROGRESS_ID10_2_0_, this_.RECIPIENT_CRID as RECIPIENT_CRID11_2_0_, this_.RETRY_COUNTER as RETRY_COUNTER12_2_0_, this_.RETRY_TIME as RETRY_TIME13_2_0_, this_.updated as updated14_2_0_ from HR.NOS_DELIVERY_DATA this_ where this_.PROGRESS=?
Hibernate: select this_.DD_ID as DD_ID1_2_0_, this_.CHANNEL_NAME as CHANNEL_NAME2_2_0_, this_.created as created3_2_0_, this_.DELIVERY_TIME as DELIVERY_TIME4_2_0_, this_.ERROR_CODE as ERROR_CODE5_2_0_, this_.ERROR_MESSAGE as ERROR_MESSAGE6_2_0_, this_.EVENT_ID as EVENT_ID7_2_0_, this_.MAX_RETRIES as MAX_RETRIES8_2_0_, this_.PROGRESS as PROGRESS9_2_0_, this_.PROGRESS_ID as PROGRESS_ID10_2_0_, this_.RECIPIENT_CRID as RECIPIENT_CRID11_2_0_, this_.RETRY_COUNTER as RETRY_COUNTER12_2_0_, this_.RETRY_TIME as RETRY_TIME13_2_0_, this_.updated as updated14_2_0_ from HR.NOS_DELIVERY_DATA this_ where this_.PROGRESS=?
Hibernate: select DD_ID from HR.NOS_DELIVERY_DATA where DD_ID =? for update
Hibernate: select DD_ID from HR.NOS_DELIVERY_DATA where DD_ID =? for update
Hibernate: update HR.NOS_DELIVERY_DATA set CHANNEL_NAME=?, created=?, DELIVERY_TIME=?, ERROR_CODE=?, ERROR_MESSAGE=?, EVENT_ID=?, MAX_RETRIES=?, PROGRESS=?, PROGRESS_ID=?, RECIPIENT_CRID=?, RETRY_COUNTER=?, RETRY_TIME=?, updated=? where DD_ID=?
Hibernate: update HR.NOS_DELIVERY_DATA set CHANNEL_NAME=?, created=?, DELIVERY_TIME=?, ERROR_CODE=?, ERROR_MESSAGE=?, EVENT_ID=?, MAX_RETRIES=?, PROGRESS=?, PROGRESS_ID=?, RECIPIENT_CRID=?, RETRY_COUNTER=?, RETRY_TIME=?, updated=? where DD_ID=?