Java 事务方法的递归ROWNUM用法

Java 事务方法的递归ROWNUM用法,java,spring,oracle,Java,Spring,Oracle,我有一个名为Person的表,我的selectsql通常会带来10万个Person,因为我有readtimeout异常需要很多时间。 所以我知道我必须使用ROWNUM来限制结果大小 Class MyService { @Transactional(rollbackFor = Exception.class) doJob(){ jobService.process(); } } Class JobService { public void process() { Li

我有一个名为Person的表,我的selectsql通常会带来10万个Person,因为我有readtimeout异常需要很多时间。 所以我知道我必须使用ROWNUM来限制结果大小

Class MyService {
  @Transactional(rollbackFor = Exception.class)
doJob(){

  jobService.process();
}

}

Class JobService {
    public void process() {
    List<Person> personlList= jdbcQuery.query ("Select * from ... ... where rownum<1000" , ROWMAPPAR, parameter);
//Process all record list
    }
在知道之前一切都正常,但我想确保所有记录(比如100K)都已处理,如果在处理其中一个批次时出现错误,则应发生回滚

我是否需要递归地涉及流程方法

使用 春季3.5
Oracle 11g

如查询中所示使用ROWNUM很可能无法得到预期的结果。但另一方面,它可能,至少有时会:-。在计算WHERE子句之后,但在应用任何ORDER BY或HAVING子句之前,当从查询中发出行时,将生成ROWNUM。这可能会导致查询返回结果,这可能会让您感到惊讶

尝试创建下表:

create table t(n number);
并将其填充为:

insert into t (n)
  select n from
   (select rownum n from dual connect by level <= 2000)
   where n > 1234;
因此,该表将有值为1235到2000的行

按顺序运行以下每个查询:

select *
  from t
  order by n;

select n, rownum
  from t
  where rownum < 100
  order by n;

select n, rownum as r from
 (select n
    from t
    order by n);

select n, r from
 (select n, rownum as r from
   (select n
      from t
      order by n))
  where r < 100
  order by n;
并观察您得到的输出的差异

对于那些手边没有Oracle实例的用户

分享和享受

我是否需要递归地涉及流程方法

我不会那么做的。只需将代码改写为:

class MyService {

  @Transactional(rollbackFor = Exception.class)
  void doJob(){

    // Continue processing within the same transaction, until process() returns false
    while (jobService.process());
  }
}

class JobService {
  public boolean process() {
    List<Person> personlList= jdbcQuery.query(
      "Select * from ... ... where rownum<=1000" , ROWMAPPAR, parameter);
    // I've changed your predicate ------^^

    // process() returns false when the above select returns less than 1000 records
    return personList.size() == 1000;
  }
}

不过,请注意,您可能遇到的一个问题是,您正在使一个非常长时间运行的事务保持活动状态。这将在数据库中导致大量并发,并可能导致批处理作业运行缓慢。如果你完全不需要一个原子批处理任务,或者所有的东西都被回滚,你可以考虑在它自己的事务中运行每个子任务。当然,这是完全正确的,但是我认为即使被接受,这也不是OP的实际问题…他们询问如何在客户端将每个批处理子任务保持在同一事务中。我认为jdbctemplate会逐fetchsize获取记录fetchsize,直到所有记录都被获取。我已经设置了fetchsize jdbctemplate.setFetchSize,然后删除ROWNUM操作符。我认为jdbctemplate通过fetchsize获取记录fetchsize,直到所有记录都被获取。最后一条记录(比如最后800条记录)的情况如何?根据您的示例,这些记录将不会被处理right@mmc18:JDBC的获取大小在这里也确实有帮助。在我的示例中,所有记录都将被处理,因为进程调用至少进行一次,或者只要前一个进程调用处理了1000条记录。因此,后面的800条记录也将被处理,但在这之后,while循环将停止。