在ResultSet.execute之后循环终止[重复]

Posted

技术标签:

【中文标题】在ResultSet.execute之后循环终止[重复]【英文标题】:While Loop Terminating after ResultSet.execute [duplicate] 【发布时间】:2017-01-08 20:30:08 【问题描述】:

我试图通过基于表 COMPA 的表 COMPB 上的更新和删除操作使 TABLE COMPB 等效于 TABLE COMPA。该代码在生成正确的 SQL 时运行良好。问题是,当我将执行语句放在下面的那一刻,while 循环在第一次迭代本身中终止。无法理解 Java 中 ResultSet 的这种行为。这里有什么帮助吗?我哪里出错了?

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


        

【问题讨论】:

我想它不喜欢你在随后的executeUpdate() 调用中重复使用stmt,但是你做了什么调试?如果您手动运行初始查询会得到什么 - 假设所有会话中的所有更改都已提交?另外,为什么要使用循环而不是单个合并语句?如果必须使用循环,为什么不使用准备好的语句和绑定变量? 谢谢亚历克斯。在循环中重用 stmt 是个问题。我还不明白它如何打破while循环。但现在我纠正了它。 我强烈建议您停止将值连接到查询字符串中,而是使用带有参数占位符的准备好的语句。您当前的代码不安全且易受 SQL 注入攻击。 @MarkRotteveel & all:感谢所有有经验的建议和花时间来完成我的小查询,尽管您的日程很忙。给了我很大的动力! 【参考方案1】:

这可能有两个原因:

重复使用相同的stmt 对象:结果集对象被映射到返回它的语句(通过executeQuery 方法),并且在迭代过程中重复使用相同的语句对象将使结果集无效。您应该创建一个新的语句对象并使用它执行这些查询。 使用CONCUR_READ_ONLY resultSet(默认):Here's Oracle 关于结果集的文档。默认情况下,它是不可修改的。如果记录需要修改,您可能需要使用CONCUR_UPDATABLE 结果集。 Here 就是一个例子。

【讨论】:

“可能使结果集无效”,尝试必须使无效;这是 JDBC 规范的要求。 @MarkRotteveel 已更正,感谢您指出。【参考方案2】:

无法理解 java 中 ResultSet 的这种行为。

您使用相同的PreparedStatement stmt 实例来执行更新:

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 seta 来自 PreparedStatement stmt 实例。 所以我认为在 PreparedStatement 实例上调用另一个执行方法会对 PreparedStatement 实例返回的先前 ResultSet 对象产生副作用。

您应该创建一个PreparedStatement 的新实例来执行您的其他查询。

【讨论】:

显示的代码使用普通的Statement 对象,但您的答案的要点是正确的。 @Mark Rotteveel 确实如此。谢谢。 @Hari Prasad 欢迎你 :)【参考方案3】:

根据下面的建议,我通过创建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"); 

               


        

【讨论】:

以上是关于在ResultSet.execute之后循环终止[重复]的主要内容,如果未能解决你的问题,请参考以下文章

matlab中break的用法

带有循环的程序不会用 CTRL + C 终止

break 和 continue 语句

js 跳出循环

[算法导论]#3 循环不变式

java中循环的不同终止方式