ORA-01002: 使用 @transactional 时不按顺序提取

pra*_*abu 1 oracle spring plsql spring-mvc mybatis

当我尝试从我的应用程序调用一个过程时出现错误,提示ORA-01002: fetch out of sequence

使用的技术:

  • Mybatis 3
  • 春季MVC

这里有趣的一点是,只有当我对服务类中的调用方法使用@Transactional (org.springframework.transaction.annotation.Transactional) 注释时才会发生错误。如果我删除@Transactional,则没有 ORA 错误。

我正在使用 @Transactional,因为我将几个 DAO 注入到服务中。请找到我粘贴在下面的代码。

@Transactional
    public boolean saveavgFlyHrs(AverageFlyingHoursReport averageFlyingHoursReport) throws TransactionDataException {
        String status = null;
        boolean isOk = false;
        if(averageFlyingHoursReportDAO.saveavgFlyHrs(averageFlyingHoursReport)) {
            status = averageFlyingHoursReportDAO.updateCheckEff(averageFlyingHoursReport.getSubFleet());
            logger.debug("OUT_STATUS:"+status);
            if(ConstantStringUtil.SUCCESS.equalsIgnoreCase(status)) {
                isOk = true;
            } else {
                isOk = false;
            }
        }
        return isOk;
    }
Run Code Online (Sandbox Code Playgroud)

任何人请帮助我。

Vin*_*rat 5

ORA-01002是 Oracle 错误。您没有显示任何 Oracle 代码,因此我们必须猜测会发生什么。

当您跨FOR UPDATE游标提交时,通常会抛出此错误,例如:

SQL> CREATE TABLE TEST (ID NUMBER, c VARCHAR2(10));

Table created

SQL> INSERT INTO TEST VALUES (1, 'a');

1 row inserted

SQL> INSERT INTO TEST VALUES (2, 'b');

1 row inserted

SQL> BEGIN
  2     FOR cc IN (SELECT * FROM TEST FOR UPDATE) LOOP -- FOR UPDATE cursor
  3        UPDATE TEST SET c = UPPER(c) WHERE ID = cc.id;
  4        COMMIT; -- this will invalidate our cursor
  5     END LOOP;
  6  END;
  7  /

ORA-01002: fetch out of sequence
ORA-06512: at line 3
Run Code Online (Sandbox Code Playgroud)

我可以想象,添加@Transactional到一个工作单元将使其成功提交/错误回滚。所以也许这段代码是使用某种FOR UPDATE游标的更大循环的一部分。当您添加时@Transactional,它会在每次调用该方法时提交,从而使主游标无效。

ORA-01002如果您在回滚一些会使游标无效的更改后尝试从游标中获取,您也可能会遇到:

SQL> DECLARE
  2     CURSOR cc IS SELECT * FROM TEST;
  3     rc cc%ROWTYPE;
  4  BEGIN
  5     UPDATE TEST SET c = 'c' WHERE ID = 2;
  6     OPEN cc;
  7     FETCH cc INTO rc;
  8     -- do other things
  9     ROLLBACK;
 10     FETCH cc INTO rc;
 11  END;
 12  /

ORA-01002: fetch out of sequence
ORA-06512: at line 11
Run Code Online (Sandbox Code Playgroud)

这里我们的游标cc无效,因为我们已经回滚了一些影响游标中行的更改。同样,这可能是由添加@Transactional和回滚事务的方法引起的,而另一个游标仍在从中获取。

总之:您应该只添加@Transactional到完成不可分割工作量的单元中。如果该方法是更大事务的子方法,则不应自行提交/回滚。