连接是一个泄漏的抽象

作为初级Java开发人员,我们在职业生涯的早期就了解JDBC API。 我们知道它是非常重要的抽象,因为它允许以透明的方式更改基础数据库。 恐怕一个好主意是过度工程,因为:

  1. 我从未见过这样的数据库迁移发生超过十年了
  2. 大多数时候,写的SQL 不是独立于数据库

尽管如此,无可否认,JDBC是Java中每个数据库交互的基础。 但是,我最近偶然发现了一个非常深藏在javax.sql.Connection接口核心的陷阱。 基本上,您可能已经被告知关闭Connection返回的Statement ? 还要关闭Statement返回的ResultSet吗? 但是也许您还被告知关闭Connection将关闭所有基础对象StatementResultSet

那么,哪个是对的? 好吧,``取决于情况'',还有麻烦......

  • 一方面,如果从DriverManager返回连接,则调用Connection.close()将关闭与数据库和所有基础对象的物理连接。
  • 另一方面,如果连接是从DataSource返回的,则调用Connection.close()只会将其返回到池中,您需要自己关闭语句。

在后一种情况下,如果不关闭这些基础语句,则数据库游标将保持打开状态,在某个时候将达到RDBMS限制,并且将不执行新的语句。 结论: 总是关闭语句对象 (就像我已经写过的一样 )! 请注意,语句结束后,结果集关闭。

如果您幸运地使用Java 7-并且不使用数据访问框架,则使用的代码如下:

try(PreparedStatementps=connection.prepareStatement("Put SQL here")){
    try(ResultSetrs=ps.executeQuery()){
        // Do something with ResultSet
    }
}catch(SQLExceptione){
    // Handle exception
    e.printStackTrace();
}

并且,如果您想确保即使错误代码也将关闭游标,那么老式的Tomcat为此提供了StatementFinalizer拦截器 。 声明Resource时,只需在server.xml配置文件中对其进行配置:

<Resourcename="jdbc/myDB"auth="Container"type="javax.sql.DataSource"
 jdbcInterceptors="org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer"/>
在那里,您还可以检查ResetAbandonedTimer拦截器。 它可以与removeAbandonedTimeout属性结合使用:这配置了将连接返回到池之前的时间。 如果属性的值太低,则可能会返回使用中的连接。 使用拦截器,每次使用连接都会重置计时器。

翻译自: https://blog.frankel.ch/connection-leaky-abstraction/

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值