Java-Can';连接关闭后,请不要使用ResultSet
我在关闭MySQL连接时遇到问题 我得到了一个错误: java.sql.SQLException:结果集关闭后不允许操作 我的代码:Java-Can';连接关闭后,请不要使用ResultSet,java,sql,jdbc,Java,Sql,Jdbc,我在关闭MySQL连接时遇到问题 我得到了一个错误: java.sql.SQLException:结果集关闭后不允许操作 我的代码: public static ResultSet sqlquery (String query) { ResultSet rs=null; Connection connection=null; Statement st=null; try{ Class.forName("com.mysql.jdbc.Driver"); conne
public static ResultSet sqlquery (String query)
{
ResultSet rs=null;
Connection connection=null;
Statement st=null;
try{
Class.forName("com.mysql.jdbc.Driver");
connection = DriverManager.getConnection("databaseadress","username","password");
st = connection.createStatement();
rs = st.executeQuery(query);
}catch(SQLException e){System.out.println("SQL error: " + e);}
catch(Exception e){System.out.println("Error: " + e);}
finally {
try{
if(rs != null) rs.close();
if(st!= null) st.close();
if(connection != null) connection.close();
}catch(SQLException e){System.out.println("SQL error : " + e);}
}
return rs;
}
这就是JDBC的工作方式。在代码中,您关闭了
结果集
和连接
,之后结果集
不再可用。如果您想让它可用,您必须将它(以及连接
)保持打开状态
但是,如果您返回
结果集
,则应该重构代码,以便调用方法提供连接
JDBC不会在结果集中返回查询的所有结果,因为可能有太多的结果而无法急切地全部获取。相反,它为您提供了一些可用于检索结果的内容,但当连接关闭时,这些内容就会消失。因此,当您在关闭数据库连接后从方法传回它时,其他任何东西都不能使用它
您可以改为让此方法使用resultSet填充对象或对象集合,然后将填充的对象传递回
如果您将代码更改为传入一个行映射器(它获取一个resultSet并传回一个用resultSet中的当前行填充的对象),并使用它来填充一个您传回的容器对象,那么您将拥有与您编写的一样可重用的东西,但这实际上是可行的,因为它不依赖于在呼叫结束后保持连接打开
下面是使用rowmapper重写的示例代码,消除了一些不必要的异常捕获,并修复了在某些情况下会阻止连接关闭的错误:
public static List<T> sqlquery (String query, RowMapper<T> rowMapper) throws SQLException
{
Connection connection=null;
Statement st=null;
ResultSet rs=null;
// don't need Class.forName anymore with type4 driver
connection = DriverManager.getConnection("databaseadress","username","password");
st = connection.createStatement();
rs = st.executeQuery(query);
List<T> list = new ArrayList<T>();
while (rs.next()) {
list.add(rowMapper.mapRow(rs));
}
// don't let exception thrown on close of
// statement or resultset prevent the
// connection from getting closed
if(rs != null)
try {rs.close()} catch (SQLException e){log.info(e);}
if(st!= null)
try {st.close()} catch (SQLException e){log.info(e);}
if(connection != null)
try {connection.close()} catch (SQLException e){log.info(e);}
return list;
}
publicstaticlist-sqlquery(字符串查询,行映射器-行映射器)抛出SQLException
{
连接=空;
语句st=null;
结果集rs=null;
//type4驱动程序不再需要Class.forName
connection=DriverManager.getConnection(“数据库地址”、“用户名”、“密码”);
st=connection.createStatement();
rs=st.executeQuery(查询);
列表=新的ArrayList();
while(rs.next()){
添加(rowMapper.mapRow(rs));
}
//不要让异常在关闭时抛出
//语句或结果集阻止
//连接无法关闭
如果(rs!=null)
尝试{rs.close()}catch(SQLException e){log.info(e);}
如果(st!=null)
请尝试{st.close()}catch(SQLException e){log.info(e);}
if(连接!=null)
请尝试{connection.close()}catch(SQLException e){log.info(e);}
退货清单;
}
如上图所示,如果您没有单独捕获在关闭时抛出的每个异常,那么如果语句或结果集在关闭时抛出异常,则可能无法关闭连接
这与spring jdbc的功能类似,它将定义为:
公共接口行映射器{
T mapRow(ResultSet,intrownum)抛出SQLException;
}
下一步是参数化查询,这样您就不必
将参数值括在引号中或担心sql注入。有关SpringJDBC如何处理此问题的示例,请参见。这里的长期答案是,采用spring jdbc或类似的东西比零碎地重新创建要好。一旦连接关闭,您就不能再使用任何资源(语句、准备好的语句、结果集),所有这些资源都会自动关闭。因此,您需要在资源打开时执行所有处理 尝试填充并返回DTO,这样您就可以在不保持连接活动的情况下获得所需的数据
RowSetFactory factory = RowSetProvider.newFactory();
CachedRowSet rowset = factory.createCachedRowSet();
rowset.populate(ResultSet data)
/*现在,您可以关闭连接并准备语句*/我不是数据库专家,但在我看来,在完成结果集之前,您不想关闭连接。那么,当您更改代码以反映这一点时会发生什么呢?为什么不从方法内的ResultSet中提取数据,并返回您希望使用数据创建的任何对象的ArrayList,然后从方法中返回此列表?您关闭了ResultSet,因此所有内容都将被删除。你为什么要用它?在关闭数据之前提取数据并返回数据异常发生在哪一行代码上?你确定这是你在这里显示的吗?看来他正在返回
ResultSet
对象,并在后面未显示的代码中获取异常。@JimGarrison是的,我知道。我希望通过检查堆栈跟踪,他会发现这一点。谢谢,这可能是最好的方法:)谢谢,解释了ResultSet是如何处理的
RowSetFactory factory = RowSetProvider.newFactory();
CachedRowSet rowset = factory.createCachedRowSet();
rowset.populate(ResultSet data)