我需要在独立(如非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);
}
}
答案 0 :(得分:0)
你的代码看起来不错,但是有一个严重的问题,你的API的客户端需要处理获取和释放连接,其中一个忘记了,内存/资源泄漏已经准备就绪。
在一个地方发布您要执行的查询,在此处进行连接,执行查询并将连接返回到池中。它将确保您返回连接。如果需要在单个连接中一个接一个地调用多个查询,则使该方法接受要按顺序执行的SQL查询的数组或列表。我们的想法是将每个请求封装到数据库中,以便管理所有连接。你可能想要编写一个你需要实现的连接(连接conn)的接口,然后你可以使用一些服务来获取这个对象给它一个连接,然后将资源释放回连接池。 类似的东西:
interface SqlWork {
execute(Connection conn);
}
SqlWork myWork = new SqlWork () {
execute(Connection conn) {
// do you work with the conn here
}
}
class SqlExecutionService {
ConnectionManager cm = ...;
public void execute(SqlWork sqlWork) {
Connection conn = null;
try {
conn = cm.getConnection();
sqlWork.execute(conn);
} catch (Your exceptions here) {
//serve or rethrow them
}
finally
{
if (conn!=null) {
cm.returnConnectionToManager(conn);
}
}
}
}
使用示例:
SqlExecutionService sqlExecService = ...;
sqlExecService.execute(myWork);