当我执行下面的代码时,我得到一个异常。我认为这是因为我正在准备新的语句与相同的连接对象。我应该如何重写这个,以便我可以创建一个准备好的语句并使用rs2?我是否必须创建一个新的连接对象,即使连接到相同的数据库?
try
{
//Get some stuff
String name = "";
String sql = "SELECT `name` FROM `user` WHERE `id` = " + userId + " LIMIT 1;";
ResultSet rs = statement.executeQuery(sql);
if(rs.next())
{
name = rs.getString("name");
}
String sql2 = "SELECT `id` FROM `profiles` WHERE `id` =" + profId + ";";
ResultSet rs2 = statement.executeQuery(sql2);
String updateSql = "INSERT INTO `blah`............";
PreparedStatement pst = (PreparedStatement)connection.prepareStatement(updateSql);
while(rs2.next())
{
int id = rs2.getInt("id");
int stuff = getStuff(id);
pst.setInt(1, stuff);
pst.addBatch();
}
pst.executeBatch();
}
catch (Exception e)
{
e.printStackTrace();
}
private int getStuff(int id)
{
try
{
String sql = "SELECT ......;";
ResultSet rs = statement.executeQuery(sql);
if(rs.next())
{
return rs.getInt("something");
}
return -1;
}//code continues
问题在于您在getStuff()
中获取数据的方式。每次你访问getStuff()
,你获得一个新的ResultSet
,但你不关闭它。
这违反了Statement
类的期望(参见这里- http://docs.oracle.com/javase/7/docs/api/java/sql/Statement.html):
默认情况下,每个Statement对象只能同时打开一个ResultSet对象。因此,如果读取一个ResultSet对象与读取另一个ResultSet对象交错,则每个ResultSet对象一定是由不同的Statement对象生成的。如果存在一个打开的ResultSet对象,Statement接口中的所有执行方法都会隐式关闭语句的当前ResultSet对象。
更糟糕的是调用代码中的rs
。它也衍生自statement
字段,但它不是封闭的。
底线:你有几个属于同一个Statement
对象的ResultSet
并发打开。
ResultSet对象是自动的关闭时的语句对象生成后关闭,重新执行,或用于检索下一个结果从多个结果的序列中。
我猜在while(rs2.next())
之后,你试图从rs1访问一些东西。但是它已经关闭了,因为你重新执行了语句,从中得到了rs2。因为你没有关闭它,我相信它在下面又使用了。