2

我试图找到允许通过 jdbc url 获取连接但失败的连接池。Hikari 连接池不允许这样做,c3po 中的情况相同。我的用例是:

ConnectionPool.getConnection(jdbcUrl);

有人知道java世界中的这种连接池吗?

4

1 回答 1

0

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();
于 2019-09-17T09:29:09.537 回答