2017-01-08 3 views
0

テーブルCOMPAに基づくテーブルCOMPBの更新と削除操作によって、TABLE COMPAをTABLE COMPAと同等にしようとしています。このコードは、適切なSQLを生成しながら完璧に動作します。問題は、次のようにexecute文を置いた瞬間ですが、ループは最初の繰り返しで終了します。 JavaのResultSetのこの動作を理解できません。どんな助け?どこが間違っていますか?WhileループがResultSet.executeの後で終了する

//Comparision between Minus Table(seta) and COMPB (setc) 
     //ID Contains Primary Key of COMPB Table 
     ResultSet seta=stmt.executeQuery("select * from COMPA minus select * from COMPB"); 


     while(seta.next()) 
     { 
      String insert=""; 
      String update=""; 
      boolean contains=ArrayUtils.contains(ID, seta.getInt(1)); 

      if (contains==true) 
      { 
       update="Update COMPB SET COMPB.EMPNAME='"+seta.getString(2)+"',COMPB.EMAILID='"+seta.getString(3)+"' where "+seta.getInt(1)+"=COMPB.EMPID"; 
       stmt.executeUpdate(update); 
       System.out.println(update); 
      } 
      else 
      { 
      insert="Insert INTO COMPB values ("+seta.getInt(1)+" , '"+seta.getString(2)+"' , '"+seta.getString(3)+"')"; 
       stmt.executeUpdate(insert); 
       System.out.println(insert); 
      } 


     } 
+0

手動で実行すると、最初のクエリはどのようになりますか?すべてのセッションのすべての変更がコミットされていると仮定します。また、なぜ1つのマージステートメントの代わりにループを使用するか。ループを使用する必要がある場合、なぜプリペアドステートメントとバインド変数を使用していないのですか? –

+0

ありがとうアレックス。ループ内でのstmtの再利用が問題でした。 whileループをどうやって破ることができるのかまだ分かりません。しかし、今はそれを修正しました。 –

+0

値をクエリ文字列に連結しないようにすることを強くお勧めします。代わりに、パラメータプレースホルダを持つプリペアドステートメントを使用してください。現在のコードは安全ではなく、SQLインジェクションに対して脆弱です。 –

答えて

1

これには二つの可能な理由が考えられます:

  • 同じstmtオブジェクトの再利用:オブジェクトは(executeQueryメソッドを介して)、それを返された声明にマッピングされ、再使用される結果セット反復の途中で同じステートメントオブジェクトが結果セットを無効にします。新しい文オブジェクトを作成し、それを使ってそれらの文を実行する必要があります。
  • 使用CONCUR_READ_ONLYresultSet(デフォルト):Here's結果セットに関するOracleのマニュアル。デフォルトでは変更できません。レコードを変更する必要がある場合は、CONCUR_UPDATABLE結果セットを使用する必要があります。 Hereがその例です。
+0

ありがとうDarshan。 –

+0

_結果セットを無効にする可能性があります_、試してください**は無効にする必要があります。これはJDBC仕様の要件です。 –

+0

@MarkRotteveelが修正されました。それを指摘してくれてありがとうございます。 –

1

javaのResultSetのこの動作を理解できません。あなたが更新を実行するために同じPreparedStatementstmtインスタンスを使用


ResultSet seta=stmt.executeQuery("select * from COMPA minus select * from COMPB"); 

while(seta.next()){ 
    ... 

    update="Update COMPB SET COMPB.EMPNAME='"+seta.getString(2)+"',COMPB.EMAILID='"+seta.getString(3)+"' where "+seta.getInt(1)+"=COMPB.EMPID"; 
    stmt.executeUpdate(update); 
    System.out.println(update); 
    ... 
    } 

あなたResultSet setaPreparedStatementstmtインスタンスから来ています。
したがって、PreparedStatementインスタンスで別のexecuteメソッドを呼び出すと、PreparedStatementインスタンスによって返された以前のResultSetオブジェクトに副作用があるとします。

他のクエリを実行するには、PreparedStatementの新しいインスタンスを作成する必要があります。

+0

ここに示すコードは通常の 'Statement'オブジェクトを使いますが、あなたの答えの要点は正しいです。 –

+0

@Mark Rotteveel確かに。ありがとうございました。 – davidxxx

+0

@ハリ・プラサード歓迎です:) – davidxxx

0

以下の提案に従って、私はpreparedstatementオブジェクトを作成してループを変更しました。私はそれはあなたがそれに続く `のexecuteUpdate()` `コール用stmt`を再利用して好きではありませんが、あなたはどのようなデバッグを行っている?想像

  while(seta.next()) 
     { 

      boolean contains=ArrayUtils.contains(ID, seta.getInt(1)); 

      if (contains==true) 
      { 


       PreparedStatement update_stmt =con.prepareStatement("Update COMPB SET COMPB.EMPNAME=?,COMPB.EMAILID=? where COMPB.EMPID=?"); 
       update_stmt.setInt(3,seta.getInt(1)); 
       update_stmt.setString(1,seta.getString(2)); 
       update_stmt.setString(2,seta.getString(3)); 
       int k=update_stmt.executeUpdate(); 
       System.out.println(k+" records updated"); 

      } 
      else 
      { 

      PreparedStatement insert_stmt =con.prepareStatement("insert into COMPB values(?,?,?)"); 
      insert_stmt.setInt(1,seta.getInt(1)); 
      insert_stmt.setString(2,seta.getString(2)); 
      insert_stmt.setString(3,seta.getString(3)); 
      int k=insert_stmt.executeUpdate(); 
      System.out.println(k+" records inserted"); 

      } 


     } 
関連する問題