简体   繁体   English

关闭池中的JDBC连接

[英]Closing JDBC Connections in Pool

Our standard code section for using JDBC is... 我们使用JDBC的标准代码部分是......

Connection conn = getConnection(...);
Statement  stmt = conn.conn.createStatement (ResultSet.TYPE_SCROLL_INSENSITIVE,
                                                ResultSet.CONCUR_READ_ONLY);
ResultSet  rset = stmt.executeQuery (sqlQuery);

// do stuff with rset

rset.close(); stmt.close(); conn.close();

Question 1: When using Connection Pool, should one close the Connection at the end? 问题1:使用连接池时,是否应该在结束时关闭连接? If so, isn't the purpose of pooling lost? 如果是这样,汇集失败的目的不是? And if not, how does the DataSource know when a particular instance of Connection is freed up and can be reused? 如果没有,DataSource如何知道什么时候释放Connection的特定实例并且可以重用? I am a little confused on this one, any pointers appreciated. 我对这个有点困惑,任何指针都赞赏。

Question 2: Is the following method anything close to standard? 问题2:以下方法是否接近标准? Looks like an attempt to get a connection from the pool, and if DataSource cannot be established, use the old fashioned DriverManager. 看起来是尝试从池中获取连接,如果无法建立DataSource,请使用旧式DriverManager。 We are not even sure which part is getting executed at runtime. 我们甚至不确定哪个部分在运行时被执行。 Repeating the question above, should one close the Connection coming out of such a method? 重复上面的问题,是否应该关闭连接出来的这种方法?

Thank you, - MS. 谢谢, - MS。

synchronized public Connection getConnection (boolean pooledConnection)
                                                        throws SQLException {
        if (pooledConnection) {
                if (ds == null) {
                        try {
                                Context envCtx = (Context)
                                        new InitialContext().lookup("java:comp/env");
                                ds = (DataSource) envCtx.lookup("jdbc/NamedInTomcat");
                                return ds.getConnection();
                        } catch (NamingException e) {
                                e.printStackTrace();
                }}
                return (ds == null) ? getConnection (false) : ds.getConnection();
        }
        return DriverManager.getConnection(
                "jdbc:mysql://"+ipaddy+":"+dbPort +"/" + dbName, uName, pWord);
}

Edit: I think we are getting the pooled connection since we do not see a stack trace. 编辑:我认为我们正在进行池化连接,因为我们没有看到堆栈跟踪。

When using Connection Pool, should one close the Connection at the end? 使用连接池时,应该在结束时关闭连接吗? If so, isn't the purpose of pooling lost? 如果是这样,汇集失败的目的不是? And if not, how does the DataSource know when a particular instance of Connection is freed up and can be reused? 如果没有,DataSource如何知道什么时候释放Connection的特定实例并且可以重用? I am a little confused on this one, any pointers appreciated. 我对这个有点困惑,任何指针都赞赏。

Yes, certainly you need to close the pooled connection as well. 是的,当然你也需要关闭池化连接。 It's actually a wrapper around the actual connection. 它实际上是实际连接的包装器。 It wil under the covers release the actual connection back to the pool. 它将在封面下释放回到池的实际连接。 It's further up to the pool to decide whether the actual connection will actually be closed or be reused for a new getConnection() call. 这是进一步向上池来决定是否实际连接实际上将被关闭或一个新的可重复使用getConnection()调用。 So, regardless of whether you're using a connection pool or not, you should always close all the JDBC resources in reversed order in the finally block of the try block where you've acquired them. 因此,无论您是否使用连接池,都应始终在已获取它们的try块的finally块中以相反的顺序关闭所有JDBC资源。 In Java 7 this can be further simplified by using try-with-resources statement. 在Java 7中,可以通过使用try-with-resources语句进一步简化。


Is the following method anything close to standard? 以下方法是否接近标准? Looks like an attempt to get a connection from the pool, and if DataSource cannot be established, use the old fashioned DriverManager. 看起来是尝试从池中获取连接,如果无法建立DataSource,请使用旧式DriverManager。 We are not even sure which part is getting executed at runtime. 我们甚至不确定哪个部分在运行时被执行。 Repeating the question above, should one close the Connection coming out of such a method? 重复上面的问题,是否应该关闭连接出来的这种方法?

The example is pretty scary. 这个例子非常可怕。 You just need to lookup/initialize the DataSource only once during application's startup in some constructor / initialization of an applicationwide DB config class. 您只需要在应用程序启动期间在应用程序范围的DB配置类的某些构造函数/初始化中查找/初始化DataSource一次。 Then just call getConnection() on the one and same datasource throughout the rest of application's lifetime. 然后在整个应用程序的生命周期中,在同一个数据源上调用getConnection() No need for synchronization nor nullchecks. 无需同步或无需检查。

See also: 也可以看看:

The pools typically return you a wrapped Connection object, where the close() method is overridden, typically returning the Connection to the pool. 这些池通常会返回一个包装的Connection对象,其中覆盖close()方法,通常会将Connection返回到池中。 Calling close() is OK and probably still required. 调用close()是可以的,可能仍然需要。

A close() method would probably look like this: close()方法可能如下所示:

public void close() throws SQLException {
  pool.returnConnection(this);
}

For your second question, you could add a logger to show whether the bottom block ever runs. 对于第二个问题,您可以添加一个记录器来显示底部块是否运行。 I would imagine though you'd only want one way or the other for the configuration of your database connections. 我想,虽然你只想要一种方式来配置数据库连接。 We solely use a pool for our database accesses. 我们只使用池来进行数据库访问。 Either way, closing the connection would be pretty important to prevent leaks. 无论哪种方式,关闭连接对于防止泄漏非常重要。

Actually, the best approach to connection management is to not farm them out to any code anywhere. 实际上,连接管理的最佳方法是不将它们分配到任何地方的任何代码。

Create a SQLExecutor class that is the one and only location which opens and closes connections. 创建一个SQLExecutor类,它是打开和关闭连接的唯一位置。

The entire rest of the application then pumps statements into the executor rather than getting connections from the pool and managing (or mismanaging them) all over the place. 然后,应用程序的其余部分将语句泵入执行程序,而不是从池中获取连接并在整个地方管理(或管理不当)。

You can have as many instances of the executor as you want, but no one should be writing code that opens and closes connections on its own behalf. 您可以根据需要拥有尽可能多的执行程序实例,但是没有人应该编写代表自己打开和关闭连接的代码。

Conveniently, this also lets you log all your SQL from a single set of code. 方便的是,这也允许您从一组代码中记录所有SQL。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM