请问各位,如何关闭JDBC中一个connection的所有resultset和statement我知道直接关闭connection也可以实现,但是因为我的程序需要不停的操作数据库,是一个电信项目,所以connection要一直保持,不去关闭它,不然开销太大,而且因为需要频繁的创建resultset和statement,如果一个个关闭太麻烦了,能否在一个操作循环完后,在一个地方关闭掉一个connection的所有resultset和statement呢?
调试欢乐多
resultset.close();
resultset=null;
(statement) :opa
opa.free();
在连接库的类里面:
// 进行数据库连接释放
public boolean free() {
try {
count--; if (stmt != null) {
if (!stmt.getConnection().isClosed()) {
stmt.close();
} }
if (connect != null) {
if (!connect.isClosed())
connect.close();
}
return true;
} catch (Exception e) {
return false;
} }
, 之后可以通过调用方法connection.closeAllStatement(),遍历你所发放在外的Statement,对其发放在外的resultset对象关闭,之后再关闭自身,这样就能达到你所要的效果。也可以调用调用statement.closeAllResultset()对象来关闭这个statement发放在外的所有的resultset对象了。
你说的我试过,但是有问题
我之前发过这个问题,但是一直没有得到满意的答案,所以我就换了个问题,贴下之前的那个问题,其实现在这个问题就是因为要解决那个问题的
最近在做的一个程序,遇到了一个JDBC方面的问题,我的代码如下
public ResultSet executeSql(String sqlstr)
{
Statement stmt = null;
ResultSet rs = null; try
{
stmt=conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
rs=stmt.executeQuery(sqlstr);
DebugLog.logger.log(Level.INFO,"获取数据集成功");
return rs;
}
catch(SQLException e)
{
DebugLog.logger.log(Level.WARNING,"获取数据集时出现错误");
DebugLog.logger.log(Level.WARNING,e.getMessage());
try{
conn.rollback();
}
catch(SQLException i)
{
DebugLog.logger.log(Level.WARNING,"回滚数据集时出现错误");
DebugLog.logger.log(Level.WARNING,i.getMessage());
}
return null;
}
catch(Exception cnfe){
DebugLog.logger.log(Level.WARNING,"获取数据集时出现错误");
DebugLog.logger.log(Level.WARNING,cnfe.getMessage());
return null;
} }
这是我之前写的一段JDBC操作数据库的代码,但是主程序运行一段时间出现这样的异常ora-01000: maximum open cursors exceeded.到网上查了下,说是已经达到一个进程打开的最大游标数,Java代码在执行conn.createStatement()和conn.prepareStatement()的时候,实际上都是相当与在数据库中打开了一个cursor。
尤其是,如果你的createStatement和prepareStatement是在一个循环里面的话,就会非常容易出现这个问题。因为游标一直在不停的打开,而且没有关闭,所以说,最好在执行了一次executeQuery、executeUpdate等之后,如果不需要使用结果集(ResultSet)的数据,就马上将Statment关闭。然后我的代码改进如下
public ResultSet executeSql(String sqlstr)
{
Statement stmt = null;
ResultSet rs = null; try
{
stmt=conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
rs=stmt.executeQuery(sqlstr);
DebugLog.logger.log(Level.INFO,"获取数据集成功");
return rs;
}
catch(SQLException e)
{
DebugLog.logger.log(Level.WARNING,"获取数据集时出现错误");
DebugLog.logger.log(Level.WARNING,e.getMessage());
try{
conn.rollback();
}
catch(SQLException i)
{
DebugLog.logger.log(Level.WARNING,"回滚数据集时出现错误");
DebugLog.logger.log(Level.WARNING,i.getMessage());
}
return null;
}
catch(Exception cnfe){
DebugLog.logger.log(Level.WARNING,"获取数据集时出现错误");
DebugLog.logger.log(Level.WARNING,cnfe.getMessage());
return null;
}finally{
try{
if(rs != null){
rs.close();
}
if(stmt != null){
stmt.close();
}
}catch(SQLException j){
DebugLog.logger.log(Level.WARNING,"关闭数据集时出现错误");
DebugLog.logger.log(Level.WARNING,j.getMessage());
}
}
}
但是这段代码的问题是,每次取这段代码执行SQL后返回的记录集,就会抛出一个信息为null的异常,我猜想是上面这个函数没返回任何记录集,rs是null的?
实在不知道什么原因,求高人指教,是什么原因?应该如何修改?谢谢了,我分不多,实在抱歉
不过还是谢谢你to XinZi(新子),谢谢你哈,恩,你的第一种方式通过上面的代码看出,是不行的,因为要返回rs
现在这个新业务除了因为有些statement用完没有关闭,运行时间长了会出现ora-01000: maximum open cursors exceeded.,业务处理上已经测试没什么问题了,所以不想大改了,否则还得重新测试?电信的这个新业务马上就要推出去了
我试下你的第三种方式
"resultset.close();"后面的“ resultset=null;”是多于的。"
Statment变量用完得关闭,特别是变量被多次赋值(stmt=conn.createStatement()),就会很容易导致ora-100之类的错误。查看JDBC源码很容易理解。
没有只是关闭所有的Statment和ResultSet而不需要关闭Connection的方法哈?
我前面已经说过,我的程序需要不停的操作数据库,是一个电信项目,所以connection要一直保持,不去关闭它,不然开销太大
只是这两个连接一直保持,不断进行数据处理,而且因为我主程序对每个数据库只进行一次连接,连接后进行数据处理,数据处理放在一个无线循环中,只是不停的执行SQL语句,不在进行数据库连接,所以整个进行一直保持的只有两个连接,哪有几千几万啊,进程异常退出才会关闭这两个连接的
没有那种关所有rs和sm的方法.
既然在循环里面就3,4句话都懒得写...
rs3 = this.Conn1.executeSql(sql3);
try{
while(rs3.next()){
........
rs4 = this.Conn1.executeSql(sql4);try{
while(rs4.next()){.........
}catch(){
}
}
}catch(){
}
请问上面这段怎么关闭statment和resultset?其中this.Conn1是和一个数据库的连接,对这个数据库嵌套做了操作,如果里层的while(rs4.next())关闭了statment和resultset,会不会影响外层的while(rs3.next())而使外层的循环不能在继续了
http://www.jspx.net/down/lib/jspxdbs-1.0.jar <bean id="jspxDataSource" class="com.jspx.datasource.JspxDataSource" destroy="close">
<string name="driverClass">${driverClassName}</string>
<string name="jdbcUrl"><![CDATA[${jdbcUrl}]]></string>
<string name="user">${username}</string>
<string name="password">${password}</string>
</bean>当你关闭的时候它不会关闭,当没有使用连接的时候会自动关闭连接。
setMaxPoolSize 设置最大连接数。
setMaxConnectionTime 最大连接等待时间,单位毫秒,超过这个时间就关闭。
rs3 = this.Conn1.executeSql(sql3);
try{
while(rs3.next()){
........
rs4 = this.Conn1.executeSql(sql4);try{
while(rs4.next()){.........
}catch(){
}
}
}catch(){
}
这样一段代码的关闭代码应该怎么写?
一个connection能带好多有效的resultset和statement吗?我怎么觉得只能1拖1 的?
应该可以,我程序里一个connection就带了好多resultset和statement,但是都能返回正确的结果
并且想通过代理接口的方式实现
后来发现不妥,只好放弃了,
因为Connection生成的Statement和ResultSet始终不释放,
而是到最后才释放,可能会达到数据库联接的最大游标数而导致错误
例如:
try{
rs1 = stmt.executeSql(sql1);
while(rs1.next()){...} rs2 = stmt.executeSql(sql2);
while(rs2.next()){...}
... rs100 = stmt.executeSql(sql4);
while(rs100.next()){...} }catch(Exception){}
finally{
closeDBSourse(rs1);//1
closeDBSourse(rs2);//2
...
closeDBSourse(rs100);//100
//1-100可能封装在函数101中 freeDBSourse(stmt);//101
}
可能在执行过程中会占用多个数据库游标,存在隐患。
目前我采用的实现方式如下,虽然比较繁琐,但很安全:
try{
rs1 = stmt.executeSql(sql1);
while(rs1.next()){...}
closeDBSourse(rs1); rs2 = stmt.executeSql(sql2);
while(rs2.next()){...}
closeDBSourse(rs2);
... rs100 = stmt.executeSql(sql4);
while(rs100.next()){...}
closeDBSourse(rs100); }catch(Exception){}
finally{
freeDBSourse(stmt);
}
public List<xxxx> executeSql(String sqlstr){}
=============================================
怎么实现这个方法呢?
ResultSet中返回的各字段属性不知道呀
是不是每个查询都要写一个这种方法,这可能要累死人
并且想通过代理接口的方式实现
后来发现不妥,只好放弃了,
因为Connection生成的Statement和ResultSet始终不释放,
而是到最后才释放,可能会达到数据库联接的最大游标数而导致错误
例如:
try{
rs1 = stmt.executeSql(sql1);
while(rs1.next()){...} rs2 = stmt.executeSql(sql2);
while(rs2.next()){...}
... rs100 = stmt.executeSql(sql4);
while(rs100.next()){...} }catch(Exception){}
finally{
closeDBSourse(rs1);//1
closeDBSourse(rs2);//2
...
closeDBSourse(rs100);//100
//1-100可能封装在函数101中 freeDBSourse(stmt);//101
}
可能在执行过程中会占用多个数据库游标,存在隐患。
目前我采用的实现方式如下,虽然比较繁琐,但很安全:
try{
rs1 = stmt.executeSql(sql1);
while(rs1.next()){...}
closeDBSourse(rs1); rs2 = stmt.executeSql(sql2);
while(rs2.next()){...}
closeDBSourse(rs2);
... rs100 = stmt.executeSql(sql4);
while(rs100.next()){...}
closeDBSourse(rs100); }catch(Exception){}
finally{
freeDBSourse(stmt);
}
应该根据自己的需求封装自己需要的数据类型,作为返回类型
这样就可以在返回之前关闭ResultSet