【问题标题】:java.sql.SQLException: ORA-01002: fetch out of sequencejava.sql.SQLException: ORA-01002: 提取乱序
【发布时间】:2012-03-28 11:56:54
【问题描述】:

我有一个演示应用程序来检查更新查询的选择

public class Test implements Runnable{

    public Test() {
    }

    public static void main(String[] args) {
        Thread t1 = new Thread(new Test());
        Thread t2 = new Thread(new Test());

        t1.start();
        t2.start();
    }

    public void run() {
        // TODO Auto-generated method stub
        try{
            String updateWith = "";
            String sel = "SELECT SIDNUMBERTO FROM tblmserialbatchdetail WHERE sidnumberto = ("+
            "SELECT max(sidnumberto) FROM tblmserialbatchdetail WHERE generationmode='A' and nvl(serialprefix,' ') = nvl('',' ') " +
            "and sidlengthwithoutprefix =12) FOR UPDATE";
            //System.out.println("SELECT QUERY ===: "+sel);
            String updatequery = "update tblmserialbatchdetail set sidnumberto = ? where serialbatchid = ?";
            System.out.println();
            Connection connection = Conn.getDBConnection();
            PreparedStatement pStatement = connection.prepareStatement(sel);

            ResultSet rSet = pStatement.executeQuery();

            while(rSet.next()){

                updateWith = rSet.getString(1);
                long value = Long.parseLong(updateWith)+1;
                updateWith = String.valueOf(value);
                System.out.println("resulet To be Updated ===> "+value);
            }
            connection.commit();
            connection.close();



        }catch (Exception e) {
            e.printStackTrace();
        }
    }

}

如果我从选择查询中删除 For update 则效果很好,否则会给我错误

java.sql.SQLException: ORA-01002: fetch out of sequence

    at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:180)
    at oracle.jdbc.ttc7.TTIoer.processError(TTIoer.java:208)
    at oracle.jdbc.ttc7.Oall7.receive(Oall7.java:543)
    at oracle.jdbc.ttc7.TTC7Protocol.doOall7(TTC7Protocol.java:1451)
    at oracle.jdbc.ttc7.TTC7Protocol.fetch(TTC7Protocol.java:943)
    at oracle.jdbc.driver.OracleStatement.doExecuteQuery(OracleStatement.java:2119)
    at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:2324)
    at oracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:421)
    at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:365)
    at com.response.Test.run(Test.java:47)
    at java.lang.Thread.run(Thread.java:595)

【问题讨论】:

    标签: java oracle jdbc


    【解决方案1】:

    SELCT ... FOR UPDATE 仅在托管事务的上下文中才有意义,因为它需要对选定的行进行锁定。

    默认情况下,JDBC 不使用托管事务,它使用一个隐式创建的事务,该事务在执行查询时立即提交。这会破坏SELECT ... FOR UPDATE 的语义,并且JDBC 驱动程序会报错。

    为了使用托管事务,添加

    connection.setAutoCommit(false); 
    

    在执行查询之前。然后执行connection.commit()

    【讨论】:

    • 是的,它可以工作,但现在进程在 ResultSet rSet = pStatement.executeQuery(); 行停止;
    • @chetan:可能是因为它无法取出锁,因为其他东西已经锁定了它。无法确定。
    • 是的,它可以将自动提交设置为 false。谢谢
    【解决方案2】:

    我得到 ORA-01002: fetch out of sequence issue with Spring JPA- Native SQL, for ORACLE MERGE statement.

    问题在于休眠会话,我修复了它,将我的数据源传递给 jdbctemplate。 排除 Spring JPA 本机 SQL 并迁移到 JDBC 模板为我解决了问题。我只遇到了 ORACLE Merge 语句的问题,而不是其他 SQL 查询。

    @豆 公共 JdbcTemplate getJdbcTemplate() 抛出异常{ 映射数据源 = applicationContext.getBeansOfType(DataSource.class); Objects.requireNonNull(dataSources, "需要数据源");

        DataSource dataSource = dataSources.entrySet().stream()
                .filter(entry->entry.getKey().startsWith("abc"))
                .map(Map.Entry::getValue)
                .findAny().orElseThrow(()-> new Exception("DataSource ABC is required."));
    
        return new JdbcTemplate(dataSource);
    }
    

    【讨论】:

      【解决方案3】:

      试试:

      connection.setAutoCommit(false); 
      

      一般来说,'select ... for update' 并不是最好的锁定策略。

      【讨论】:

      • 你能提供替代方案吗?
      • 如果我不知道您要解决的问题,我该如何提供替代方案? :)
      【解决方案4】:

      您可以使用executeUpdate 函数而不是使用executeQuery。 不要使用“选择更新”,而是直接尝试更新一个事务中的行,这将为您提供更新的行数。这样,例如,当两个事务尝试更新一行时,第一个赢得另一个返回零,并且您知道第一个成功更新,因为它将返回更新的行数。

      【讨论】:

        猜你喜欢
        • 2013-04-19
        • 2016-07-11
        • 2013-09-07
        • 2023-03-04
        • 2020-10-13
        • 2016-06-09
        • 2021-06-04
        相关资源
        最近更新 更多