gpt4 book ai didi

java.sql.SQLException : ResultSet closed on sqlite 异常

转载 作者:行者123 更新时间:2023-11-29 08:40:06 27 4
gpt4 key购买 nike

我看了很多答案,但不幸的是没有一个回答我的问题,我仍然无法弄清楚为什么我要关闭 ResultSet

这是导致问题的 try 代码片段:

        System.out.println(" System Info! @CHKMD5Files(): Found pre-existing details: "+TOTAL);

Statement stmMD5 = null;
Connection connMD5 = null;
ResultSet rs_MD5 = null;
String RESULTMD5 = null;

try {
connMD5 = DriverManager.getConnection("jdbc:sqlite:" + bkpPATH+ hostname + ".db");
stmMD5 = connMD5.createStatement();
connMD5.setAutoCommit(false);

while (ROWID <= TOTAL) {
rs_MD5 = stmMD5.executeQuery("SELECT md5 FROM details WHERE ROWID = '"+ROWID+"';");
RESULTMD5 = rs_MD5.getString("MD5");
skipBuffer.write(RESULTMD5);
skipBuffer.newLine();
skipBuffer.flush();
ROWID++;
}
System.out.println(" System Info! @CHKMD5Files(): Done with try");

} catch (Exception ex) {
System.out.println(" System Error! @CHKMD5Files (2): " + ex);
System.exit(5);
} finally {
if (stmMD5 != null){
stmMD5.close();
System.out.println(" System Info! @CHKMD5Files (2): Closing Statement(stmMD5)");
}
if (connMD5 != null) {
connMD5.close();
System.out.println(" System Info! @CHKMD5Files (2): Closing Connection(connMD5)");
}
skipBuffer.close();
}
}

看起来 while 循环甚至没有运行,因为如果我将 print 语句放入循环中则什么也不会返回。

最佳答案

当你想使用一个ResultSet时,你必须调用next方法首先将 ResultSet 的指针设置在结果的第一行。作为Javadoc该方法说:

A ResultSet cursor is initially positioned before the first row; the first call to the method next makes the first row the current row; ...

因此,如果您不调用它,则不会指向任何结果和 getString 方法(在 RESULTMD5 = rs_MD5.getString("MD5") 中使用);) 将生成该异常。所以至少添加

rs_MD5.next()

在提取结果之前。 next 方法返回一个 boolean 值以指示它是否可以到达下一行。所以你可能想添加一个 if 语句来在提取任何列值之前检查该值是否为真,因为如果 next 无法到达下一行(并返回false) 它会将指针设置为无有效行(没有剩余行),如果您尝试访问结果,您将得到相同的错误(请参阅上面 next 的 javadoc 链接)。

但不幸的是,即使您添加对next 的调用,您也会在第二次迭代中遇到同样的错误,因为您不能使用相同的 Statement - 执行不同查询的对象。每个Statement对象只能产生一个ResultSet
要解决这个问题,你至少应该更换

rs_MD5 = stmMD5.executeQuery("SELECT md5 FROM details WHERE ROWID = '"+ROWID+"';");

rs_MD5 = connMD5.createStatement().executeQuery(
"SELECT md5 FROM details WHERE ROWID = '"+ROWID+"';"
);

但我建议您不这样做,因为创建一个新的 Statement 对象非常耗时(每个对象都必须在执行之前进行编译)。由于在每次迭代中唯一改变的是 ROWID,因此在每次迭代中再次重新编译相同的东西将是一种可怕的时间浪费。所以使用 PreparedStatement反而。它允许您使用仅编译一次的语句,并且可以通过在其中注入(inject)参数(编译后)来多次重复使用。要使用 PreparedStatement,您应该这样做:

Connection conn = ... //Connection to your database
PreparedStatement ps = conn.preparedStatement("SELECT * FROM person WHERE name = ? AND age = ?");

//First search all persons with name "J.Baoby" and age = 5
ps.setString(1, "J.Baoby");
ps.setInt(2, 5);
ResultSet set1 = ps.executeQuery();
// Do something with it
// ....

//Now I need persons with name "Henry" and age = 25
ps.setString(1, "Henry");
ps.setInt(2, 25);
ResultSet set1 = ps.executeQuery();
// Do something with it
// ...

注入(inject)这些参数的方法是使用 setXXX 方法,第一个参数是“?”的索引(从 1 开始)。你想替换,第二个参数是值。 XXX 替换为您要注入(inject)的值的类型。您可以注入(inject)的参数类型有限,因此请查看 Java API首先在其中注入(inject)对象之前。您可以在 Java API 中找到有关 PreparedStatement 的更多信息或 on this site (还有更多示例)。

最后我想补充一点,您应该关闭所有 (JDBC) 资源(ConnectionStatementResultSetPreparedStatement, ...) 当你确定你不再需要它们时。您不释放的资源是您的 JVM 可以分配给其他东西的浪费资源。不关闭资源是一个坏习惯,可能会导致性能下降。

祝你好运!

关于java.sql.SQLException : ResultSet closed on sqlite 异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40913684/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com