JDBC中关于Connection, PreparedStatement, ResultSet是否关闭的一些思考

如果你不使用连接池,那么就没有什么问题,一旦Connection关闭,数据库物理连接就被释放,所有相关Java资源也可以被GC回收了。但是如果你使用连接池,那么请注意,Connection关闭并不是物理关闭,只是归还连接池,所以PreparedStatement和ResultSet都被持有,并且实际占用相关的数据库的游标资源,在这种情况下,只要长期运行,往往就会报“游标超出数据库允许的最大值”的错误,导致程序无法正常访问数据库。

在使用java开发后台应用程序的时候,如果需要使用数据库,特别是试用第三方的数据库连接池的时候,使用完PreparedStatement等一定要手动关闭,最好是将关闭的代码写到finally中,保证一定能够完成关闭。   

原因有如下两点:

1、第三方的数据库连接池,使用的时候,获取到Connection之后,使用完成,调用的关闭方法(close()) ,并没有将Connection关闭,只是放回到连接池中,如果调用的这个方法,而没有手动关闭PreparedStatement等,则这个PreparedStatement并没有关闭,这样会使得开发的程序内存急速增长,java的内存回收机制可能跟不上速度,最终造成Out of memory Error。

2、如过在PreparedStatement等调用的时候,发生异常,则这个PreparedStatement是没有被关闭的,因此最好将PreparedStatement等的关闭写到finally代码中。下面是本人

在本机上试过的一个测试实例

	public static List<OrgzMetaDto> queryMetaByOrgzName1() {
		String sql = "SELECT * FROM test_table limit 0, 10000";
		List<OrgzMetaDto> orgzs = new ArrayList<OrgzMetaDto>();
		try {
			pst = conn.prepareStatement(sql);
			ResultSet resultSet = pst.executeQuery();
			while (resultSet.next()) {
				OrgzMetaDto dto = new OrgzMetaDto();
				dto.setUuid(resultSet.getString("uuid"));
				orgzs.add(dto);
			}
                        resultSet.close();
	 	} catch (Exception e) {
			e.printStackTrace();
		}
		return orgzs;
	}
	
	public static void main(String[] args) throws Exception {
		for (int i=0; i<1000; i++) {
			System.out.println(i);
			queryMetaByOrgzName1();
		}
	}

可以自行用类似于上述的代码测试一下 , 测试的时候关注本机物理内存的占用状况
在有resultSet.close()这句代码的时候,内存占用并不会发生太大变化,而一旦不关闭结果集,内存占用将会急速增长,甚至程序被hang住,我猜测可能就是上述所说的“游标超出数据库允许的最大值”,就算不阻塞,内存占用继续增长,将出现内存溢出问题

                
  • 8
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值