在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之后循环终止[重复]的主要内容,如果未能解决你的问题,请参考以下文章