2012-03-28 13 views
0

我有一个演示应用程序来检查选择更新查询值java.sql.SQLException:ORA-01002:取乱序

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

} 

如果我删除对于从选择查询更新,否则给我的错误也能正常工作

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) 

回答

6

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

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

为了使用管理的事务,加上

connection.setAutoCommit(false); 

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

+0

是的,它的工作,但现在过程停止在行ResultSet rSet = pStatement.executeQuery(); – chetan 2012-03-28 12:35:06

+0

为什么过程停止? – chetan 2012-03-28 12:35:45

+0

@chetan:可能是因为它不能取出锁,因为其他东西已经锁定了它。不可能肯定地说。 – skaffman 2012-03-28 12:36:41

0

尝试:

connection.setAutoCommit(false); 

作为一般的笔记, 'SELECT ... FOR UPDATE' 是不是最好的LO cking策略。

+1

你能解释你的答案吗? – 2012-03-28 12:20:12

+0

但它工作? – maximdim 2012-03-28 12:30:57

+0

可否请您提供替代? – chetan 2012-03-28 12:39:35

0

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