我试图找到允许通过 jdbc url 获取连接但失败的连接池。Hikari 连接池不允许这样做,c3po 中的情况相同。我的用例是:
ConnectionPool.getConnection(jdbcUrl);
有人知道java世界中的这种连接池吗?
我试图找到允许通过 jdbc url 获取连接但失败的连接池。Hikari 连接池不允许这样做,c3po 中的情况相同。我的用例是:
ConnectionPool.getConnection(jdbcUrl);
有人知道java世界中的这种连接池吗?
作者 - Baeldung
一个简单的实现
为了更好地理解连接池的底层逻辑,让我们创建一个简单的实现。
让我们从仅基于一个接口的松散耦合设计开始:
public interface ConnectionPool {
Connection getConnection();
boolean releaseConnection(Connection connection);
String getUrl();
String getUser();
String getPassword();
}
ConnectionPool 接口定义了基本连接池的公共 API。
现在,让我们创建一个实现,它提供一些基本功能,包括获取和释放池连接:
public class BasicConnectionPool
implements ConnectionPool {
private String url;
private String user;
private String password;
private List<Connection> connectionPool;
private List<Connection> usedConnections = new ArrayList<>();
private static int INITIAL_POOL_SIZE = 10;
public static BasicConnectionPool create(
String url, String user,
String password) throws SQLException {
List<Connection> pool = new ArrayList<>(INITIAL_POOL_SIZE);
for (int i = 0; i < INITIAL_POOL_SIZE; i++) {
pool.add(createConnection(url, user, password));
}
return new BasicConnectionPool(url, user, password, pool);
}
// standard constructors
@Override
public Connection getConnection() {
Connection connection = connectionPool
.remove(connectionPool.size() - 1);
usedConnections.add(connection);
return connection;
}
@Override
public boolean releaseConnection(Connection connection) {
connectionPool.add(connection);
return usedConnections.remove(connection);
}
private static Connection createConnection(
String url, String user, String password)
throws SQLException {
return DriverManager.getConnection(url, user, password);
}
public int getSize() {
return connectionPool.size() + usedConnections.size();
}
// standard getters
}
连接池是一种众所周知的数据访问模式,其主要目的是减少执行数据库连接和读/写数据库操作所涉及的开销。
简而言之,连接池在最基本的层面上是一种数据库连接缓存实现,可以对其进行配置以满足特定需求。
在本教程中,我们将快速总结一些流行的连接池框架,我们将学习如何从头开始实现我们自己的连接池。
为什么要连接池?
当然,这个问题是修辞性的。
如果我们分析典型数据库连接生命周期中涉及的步骤顺序,我们就会明白为什么:
使用数据库驱动程序打开与数据库的连接 打开 TCP 套接字以读取/写入数据 通过套接字读取/写入数据 关闭连接 关闭套接字 很明显,数据库连接是相当昂贵的操作,因此应该减少在每个可能的用例中都尽量减少(在边缘情况下,只是避免)。
这就是连接池实现发挥作用的地方。
通过简单地实现一个数据库连接容器,它允许我们重用许多现有的连接,我们可以有效地节省执行大量昂贵的数据库旅行的成本,从而提高我们数据库驱动应用程序的整体性能。
JDBC 连接池框架
从实用的角度来看,考虑到可用的“企业就绪”连接池框架的数量,从头开始实施连接池毫无意义。
从一个说教的角度来看,这是本文的目标,它不是。
尽管如此,在我们学习如何实现一个基本的连接池之前,让我们先展示几个流行的连接池框架。
Apache Commons DBCP
public class DBCPDataSource {
private static BasicDataSource ds = new BasicDataSource();
static {
ds.setUrl("jdbc:h2:mem:test");
ds.setUsername("user");
ds.setPassword("password");
ds.setMinIdle(5);
ds.setMaxIdle(10);
ds.setMaxOpenPreparedStatements(100);
}
public static Connection getConnection() throws SQLException {
return ds.getConnection();
}
private DBCPDataSource(){ }
}
在本例中,我们使用了带有静态块的包装类来轻松配置 DBCP 的属性。
以下是如何使用 DBCPDataSource 类获得池连接:
connection con = DBCPDataSource.getConnection();
光CP
public class HikariCPDataSource {
private static HikariConfig config = new HikariConfig();
private static HikariDataSource ds;
static {
config.setJdbcUrl("jdbc:h2:mem:test");
config.setUsername("user");
config.setPassword("password");
config.addDataSourceProperty("cachePrepStmts", "true");
config.addDataSourceProperty("prepStmtCacheSize", "250");
config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
ds = new HikariDataSource(config);
}
public static Connection getConnection() throws SQLException {
return ds.getConnection();
}
private HikariCPDataSource(){}
}
同样,这里是如何获得与 HikariCPDataSource 类的池连接:
Connection con = HikariCPDataSource.getConnection();