java.sql.SQLException:ORA-01002:提取失序

时间:2012-03-28 11:56:55

标签: java oracle jdbc

我有一个演示应用程序来检查select for update query

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();
        }
    }

}

如果我从select查询中删除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)

4 个答案:

答案 0 :(得分:6)

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

默认情况下,JDBC不使用托管事务,它使用隐式创建的事务,一旦执行查询就会提交。这将打破SELECT ... FOR UPDATE的语义,并且JDBC驱动程序会抱怨。

要使用托管交易,请添加

connection.setAutoCommit(false); 

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

答案 1 :(得分:1)

我得到了ORA-01002:对于Oracle MERGE语句,使用Spring JPA-Native SQL提取顺序不正确的问题。

问题与休眠会话有关,我修复了将其数据源传递给jdbctemplate的问题。 不包括Spring JPA本机SQL并迁移到JDBC模板对我来说解决了问题。我仅对ORACLE Merge语句有问题,而对其他SQL查询则没有问题。

@Bean     公共JdbcTemplate getJdbcTemplate()引发异常{         地图dataSources = 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);
}

答案 2 :(得分:0)

尝试:

connection.setAutoCommit(false); 

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

答案 3 :(得分:0)

而不是使用executeQuery,您可以使用executeUpdate函数。 不要使用“select for update”而是直接尝试更新一个事务中的行,这将为您提供更新的行数。这种方式,例如当两个事务尝试更新一行时,第一个赢得其他返回零,并且您知道首先成功更新,因为它将返回更新的rowcount。