【发布时间】:2016-07-15 18:40:43
【问题描述】:
我需要在独立(如非 Web)Java 应用程序中使用连接池。在我工作的地方,我们不允许在没有经过安全层的情况下使用 API,而且这项工作需要尽快完成。下面是我创建此连接池的尝试。
我已经对这段代码进行了单元测试,并在整个应用程序的上下文中对其进行了一百次测试,在所有情况下,测试都以零错误通过,此外,每次运行的性能比以串行方式进行简单连接、检索数据、断开连接;但是,我仍然担心这种方法可能存在我尚未发现的问题。如果有人对以下代码提出任何建议,我将不胜感激。这是我在这个网站上的第一篇文章;如果我在礼仪上犯了任何错误,请告诉我。在发布之前,我确实在这个网站上搜索过这个问题。请参阅下面的代码以获取调用示例。谢谢。 --JR
package mypackage;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
/**
* Note: This class is only instantiated once per application run.
* Multiple instantiations, as specified in the release notes,
* are not supported.
*/
public class ConnectionManager {
// Use a blocking queue to store the database connections.
// The application will only be called once, by a single user,
// but within the application many threads will require
// a connection.
private BlockingQueue<Connection> connectionQueue = null;
// Load the connection queue with a user-defined number of connections.
// Params contains a map of all non hard-coded variables in the
// application.
public ConnectionManager(int howMany, Map<String, Object> params) {
Database database = new Database();
connectionQueue = new ArrayBlockingQueue<Connection>(howMany);
for(int i = 0; i < howMany; i++) {
connectionQueue.add(database.getConn(params));
}
}
// Return a connection from the queue, waiting up to 15 minutes to do so.
// 15 minutes is hard-coded because it is the standard time-out for all
// processes at our agency. This application must complete in less
// than fifteen minutes (is currently completing in thirty five seconds).
public Connection getConnection() {
Connection conn = null;
try {
conn = connectionQueue.poll(15, TimeUnit.MINUTES);
}
catch(InterruptedException e) {
e.printStackTrace();
}
catch(SQLException e) {
e.printStackTrace();
}
return conn;
}
// Returns a connection to the connection queue.
public void returnConnectionToManager(Connection conn) {
connectionQueue.add(conn);
}
// Called on the last line of the application program's dispatcher.
// Closes all active connections (which will only exist if there
// was a failure within one of the worker threads).
public void closeAllConnections() {
for(Connection conn : connectionQueue) {
try {
conn.close();
}
catch(SQLException e) {
e.printStackTrace();
}
}
}
}
调用示例:
...
private ConnectionManager cm;
...
public Table(Map<String, Object> params, String method) {
...
cm = (ConnectionManager) params.get("cm");
}
// Execute a chunk of SQL code without requiring processing of a
// result set. Acquires connection from pool via cm.getConnection
// and releases connection via cm.returnConnectionToManager.
// (Database is just a helper class with simple methods for
// closing prepared statement, result sets, etc.)
private void execute(String sql) {
PreparedStatement ps = null;
Connection conn = null;
try {
conn = cm.getConnection();
ps = conn.prepareStatement(sql);
ps.execute();
}
catch (SQLException e) {
e.printStackTrace();
}
finally {
database.closePreparedStatement(ps);
cm.returnConnectionToManager(conn);
}
}
【问题讨论】:
-
将对象存储到单例类或枚举中。最好是枚举。通过这种方式,您的连接池将易于访问并轻松避免多个对象。添加一个方法以在您的应用程序代码完成数据库事务后释放单个连接。
-
Where I work, we are not allowed to use APIs without going through layers of security..听起来像是 Not Invented Here 的糟糕案例。为什么有些人认为内部代码比经过数千人尝试和测试的开源框架更安全,这总是让我感到惊讶。 -
IMO 而不是编写自己的代码来清除 API 会更好
-
创建一个发布查询以执行的地方,在这个地方建立连接,执行查询并将连接返回到池中。它将确保您返回连接。如果您需要在单个连接中一个接一个地调用多个查询,请使该方法接受要按顺序执行的 SQL 查询的数组或列表。
-
Ace,我希望我可以选择为此获得一个 API,但要实现这一点几乎需要国会法案。十年后,我什至放弃了尝试。
标签: java jdbc connection pool