关闭连接:java中的下一个
我有一个ResultSet方法,我正在关闭Finally块中的连接:关闭连接:java中的下一个,java,jdbc,Java,Jdbc,我有一个ResultSet方法,我正在关闭Finally块中的连接: public static ResultSet countdrcountcr(String vforacid) throws SQLException { ResultSet rs = null; Connection conn = null; try { conn = db.getDbConnection(); String
public static ResultSet countdrcountcr(String vforacid) throws SQLException {
ResultSet rs = null;
Connection conn = null;
try {
conn = db.getDbConnection();
String sql = "SELECT NVL (SUM (DECODE (part_tran_type, 'D', 1, 0)), 0), "
+ " NVL (SUM (DECODE (part_tran_type, 'C', 1, 0)), 0) "
+ " FROM tbaadm.htd WHERE acid IN (SELECT acid "
+ " FROM tbaadm.gam WHERE foracid = '" + vforacid + "') "
+ " AND tran_date >= '22-NOV-2013' AND tran_date <= '30-NOV-2013' "
+ " AND pstd_flg = 'Y' AND del_flg != 'Y'";
PreparedStatement ps = conn.prepareStatement(sql);
rs = ps.executeQuery();
return rs;
} finally {
conn.close();
}
}
我做的什么不对?您正在关闭finally块中的底层
连接
。。。您没有关闭PreparedStatement(您应该这样做,但也需要在使用结果集之后关闭它)。使用调用者的finally块(在这里打开连接
)。此外,您可能需要考虑使用.您返回“代码”> ReultSts<代码>以供将来使用,但在使用完之后,您将关闭连接,因此,由于资源已经关闭,所以无法检索数据。请注意,始终调用finally
,即使您在try
或catch
代码块中返回了某些内容,请参阅
具体而言,这就是问题所在:
打开连接
准备一份声明
获取结果集
返回结果集
关闭连接(这可能会关闭相关资源,即它可能会关闭与当前连接关联的PreparedStatement
和ResultSet
),因为,如前面链接中所述,最后
块始终执行,至少在JVM崩溃或您使用系统手动完成应用程序时执行。退出
使用关闭的结果集
。由于前面的步骤,它已关闭
一种可能的解决方案是,您的countdrcountcr
方法和返回ResultSet
的所有其他方法将连接作为参数接收,因此调用它的方法将处理连接的打开和关闭。另外,请注意,如果您在多线程环境(例如web应用程序)中工作,则不应使用静态方法来处理数据库操作。您不能关闭连接,然后使用结果集
。您必须首先完成使用结果集
,然后在某个时候关闭连接
。通常情况下,首先在“数据访问对象”中完成结果集的工作,然后返回数据作为对象的一些封装表示。Luiggi的回答是正确的,但OP似乎不明白为什么关闭连接会阻止结果集工作,因为代码在连接关闭之前获得了结果集
有一种流行的误解,认为ResultSet必须是某种数据保存对象,可以用来传递数据。事实并非如此。它只是对数据库游标的引用,在您对其调用next()
之前,它实际上并没有获取某一行的数据。它需要带电连接才能工作。在关闭连接之前,需要将查询结果解压缩到集合(通常是列表)中
顺便说一句,不要使用字符串连接将参数添加到SQL中,这会使您面临SQL注入(同时处理引用参数也是一件痛苦的事情)。您可以将?
添加到SQL中,并通过调用preparedStatement上的方法为参数添加值
如果您使用SpringJDBC,它将为您处理所有繁琐的JDBC内容(包括关闭所有需要关闭的内容),您所要处理的就是实现一个行映射器来描述如何将数据从结果集移动到集合中。我认为您的查询需要很长时间才能执行,并且会被驱动程序/tomcat级别终止
检查应用程序上下文xml文件中的参数RemoveBandonedTimeout值
删除BandonedTimeout=300
也就是说,如果任何运行超过300秒的查询都将被JDBC驱动程序关闭。这样做是为了避免连接池“泄漏”。要解决此问题,可以使用更高的数字设置该值
有关此参数和其他相关参数的更多信息,请参见如果您当时试图关闭while块内的连接,您也可以获得此类异常…因此请在while块后关闭连接
package com.literals;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class DataBaseDemo {
public static void main(String[] args) {
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
System.out.println("driver is loading...........");
Connection con=DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:mytest","SYSTEM","murali");
System.out.println("connection is established");
Statement st=con.createStatement();
System.out.println("statement is created");
ResultSet rs=st.executeQuery("select * from student");
while(rs.next()){
System.out.println(rs.getString(1)+" "+rs.getInt(2)+" "+rs.getString(3)+"");
con.close();
}
} catch (ClassNotFoundException | SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
如上所述:另外,请注意,如果您在多线程环境(例如web应用程序)中工作,则不应使用静态方法来处理数据库操作
这真的很有帮助。我遇到了一个类似的问题,我的连接在循环中被关闭,因此无法在下一轮中检查。为了修复,我放置了con.close()代码>在循环之外,这解决了问题。像这样:
while (rs.next()) {
String name = rs.getString("NAME");
}
con.close(); //placed outside the loop
}
你能指出发生错误的那一行并把你的stacktrace放在你的问题上吗?你正在关闭连接,但仍然使用resultset。是的,我在关闭之前返回了值。当(rs1.next())
尝试调用此结果集时,出现了错误。如果在con.close()之前设置了返回值,请解释一下原因;我的意思是,控制流Execute all code=>rs已经引用到行集合=>返回此值=>并关闭连接。如果已经引用了值,为什么con还需要连接?这个答案解决了我的问题。我们使用的是tomcat池,如果连接超过RemoveBondonedTime,驱动程序就会关闭连接,很高兴它起到了作用。
while (rs.next()) {
String name = rs.getString("NAME");
}
con.close(); //placed outside the loop
}