java.sql.SQLException:结果集在sqlite上关闭
我看了很多答案,但不幸的是没有一个答案能回答我的问题,我仍然不明白为什么我要关闭java.sql.SQLException:结果集在sqlite上关闭,java,sqlite,jdbc,sqlexception,Java,Sqlite,Jdbc,Sqlexception,我看了很多答案,但不幸的是没有一个答案能回答我的问题,我仍然不明白为什么我要关闭ResultSet 以下是导致问题的try代码片段: System.out.println(" System Info! @CHKMD5Files(): Found pre-existing details: "+TOTAL); Statement stmMD5 = null; Connection connMD5 = null; ResultSet
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();
}
}
System.out.println(“系统信息!@CHKMD5Files():找到预先存在的详细信息:“+TOTAL”);
语句stmMD5=null;
连接connMD5=null;
结果集rs_MD5=null;
字符串RESULTMD5=null;
试一试{
connMD5=DriverManager.getConnection(“jdbc:sqlite:+bkpPATH+hostname+.db”);
stmMD5=connMD5.createStatement();
connMD5.setAutoCommit(false);
而(ROWID当您想要使用ResultSet
时,必须首先调用该方法,以在结果的第一行上设置ResultSet
的指针。正如该方法的说明:
ResultSet游标最初位于第一行之前;对方法next的第一次调用使第一行成为当前行
因此,如果不调用它,就不会指向“无结果”,并且getString
方法(在RESULTMD5=rs_MD5.getString(“MD5”);
中使用)将生成该异常
rs_MD5.next()
在提取结果之前。next
方法返回一个布尔值,指示它是否可以到达下一行。因此,您可能需要添加一个if
-语句,在提取任何列值之前检查该值是否为真,因为如果next
无法到达下一行(并返回false)它会将指针设置为无有效行(没有剩余行),如果您尝试访问结果,您将得到相同的错误(请参阅上面的链接至next
)
但不幸的是,即使要添加对next
的调用,在第二次迭代中也会出现相同的错误,因为不能使用相同的语句
-对象来执行不同的查询。
每个语句
-对象只能产生一个结果集
要解决这个问题,您至少应该替换
与
但我建议您不要这样做,因为创建一个新的语句
-对象非常耗时(每个对象在执行之前都必须编译)。由于在每次迭代中唯一更改的是ROWID
,因此在每次迭代中重新编译相同的内容将是一种严重的时间浪费。因此请改用。它允许您使用只编译一次的语句,并且可以通过在语句中注入参数(编译后)重复使用多次。
要使用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
// ...
注入这些参数的方法是使用setXXX
方法,将“”的索引(基于1)作为第一个参数您要替换,第二个参数是值。XXX
被替换为您要注入的值的类型。您只能注入有限类型的参数,因此在注入对象之前检查第一个参数。
您可以在中找到有关PreparedStatement
的更多信息
或者(再举一些例子)
最后,我想补充一点,您应该关闭所有(JDBC)资源(连接
,语句
,结果集
,准备语句
,…)当您确定不再需要它们时。您不发布的资源是浪费的资源。您的JVM本可以分配给其他资源。不关闭您的资源是一个坏习惯,可能会导致性能下降
祝你好运!如果你想使用结果集
,你必须首先调用该方法,在结果的第一行设置结果集
的指针。正如该方法的说明:
ResultSet游标最初位于第一行之前;对方法next的第一次调用使第一行成为当前行
因此,如果不调用它,就不会指向“无结果”,并且getString
方法(在RESULTMD5=rs_MD5.getString(“MD5”);
中使用)将生成该异常
rs_MD5.next()
在提取结果之前。next
方法返回一个布尔值,指示它是否可以到达下一行。因此,您可能需要添加一个if
-语句,在提取任何列值之前检查该值是否为真,因为如果next
无法到达下一行(并返回false)它会将指针设置为无有效行(没有剩余行),如果您尝试访问结果,您将得到相同的错误(请参阅上面的链接至next
)
但不幸的是,即使要添加对next
的调用,在第二次迭代中也会出现相同的错误,因为不能使用相同的语句
-对象来执行不同的查询。
每个语句
-对象只能产生一个结果集
要解决这个问题,您至少应该替换
与
但我建议您不要这样做,因为创建一个新的语句
-对象非常耗时(每个对象在执行之前都必须编译)。由于在每次迭代中唯一更改的是ROWID
,因此在每次迭代中重新编译相同的内容将是一种严重的时间浪费。因此请改用。它允许您使用只编译一次的语句,并且可以通过在语句中注入参数(编译后)重复使用多次。
要使用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
// ...
注入这些参数的方法是使用setXXX
方法,第一个参数是要替换的“?”的索引(基于1),第二个参数是值。XXX
被值的类型替换
while (ROWID <= TOTAL) {
rs_MD5 = stmMD5.executeQuery("SELECT md5 FROM details WHERE ROWID = '"+ROWID+"';");
if (!rs_MD5.next() ) {
System.out.println(" System Info! @CHKMD5Files(): No data in rowid: "+ROWID);
ROWID++;
} else {
RESULTMD5 = rs_MD5.getString("MD5");
skipBuffer.write(RESULTMD5);
skipBuffer.newLine();
skipBuffer.flush();
ROWID++;
rs_MD5.close();
}
}