2017-01-08 7 views
0

테이블 COMPA를 테이블 COMPA에 기반한 테이블 COMPB의 업데이트 및 삭제 작업으로 TABLE COMPA와 동일하게 만들려고합니다. 이 코드는 적절한 SQL을 생성하는 동안 완벽하게 작동합니다. 문제는, 내가 루프를 첫 번째 반복 자체에서 종료하는 동안 실행 문을 넣어 아래와 같습니다. 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

후속 executeUpdate() 호출에 대해 stmt를 재사용하는 것을 좋아하지 않는다고 생각하지만 어떤 디버깅을 했습니까? 수동으로 실행하는 경우 초기 쿼리는 무엇입니까? 모든 세션의 모든 변경 사항이 커밋되었다고 가정합니다. 또한, 왜 하나의 병합 문 대신 루프를 사용하십시오; 루프를 사용해야하는 경우 준비된 문과 변수를 바인드하지 않는 이유는 무엇입니까? –

+0

감사합니다. Alex. 루프 내에서 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 동작을 이해할 수 없습니다.

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 stmt 인스턴스를 사용합니다.
PreparedStatement 인스턴스에서 다른 execute 메소드를 호출하면 PreparedStatement 인스턴스가 반환 한 이전 ResultSet 객체에 부작용이 있다고 가정합니다.

다른 쿼리를 실행하려면 PreparedStatement의 새 인스턴스를 만들어야합니다.

+0

표시된 코드는 일반적인 'Statement' 객체를 사용하지만 답변의 요지는 맞습니다. –

+0

@Mark Rotteveel 실제로. 고맙습니다. – davidxxx

+0

@ 하리 프라 사드 환영합니다 :) – davidxxx

0

아래의 제안에 따라 필자는 preparedstatement 객체를 만들어 루프를 변경했습니다.

  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"); 

      } 


     }