第九章 连接池

连接池的理解

不使用连接池有啥问题

Connection对象是重量级对象,创建Connection对象就是建立两个进程之间的通信,非常耗费资源。一次完整的数据库操作,大部分时间都耗费在连接对象的创建。

第一个问题:每一次请求都创建一个Connection连接对象,效率较低。

第二个问题:连接对象的数量无法限制。如果连接对象的数量过高,会导致mysql数据库服务器崩溃。

使用连接池来解决什么问题

提前创建好N个连接对象,将其存放到一个集合中(这个集合就是一个缓存)。

用户请求时,需要连接对象直接从连接池中获取,不需要创建连接对象,因此效率较高。

另外,连接对象只能从连接池中获取,如果没有空闲的连接对象,只能等待,这样连接对象创建的数量就得到了控制。

javax.sql.DataSource

连接池有很多,不过所有的连接池都实现了 javax.sql.DataSource 接口。也就是说我们程序员在使用连接池的时候,不管使用哪家的连接池产品,只要面向javax.sql.DataSource接口调用方法即可。

另外,实际上我们也可以自定义属于我们自己的连接池。只要实现DataSource接口即可。

连接池的属性

对于一个基本的连接池来说,一般都包含以下几个常见的属性:

  1. 初始化连接数(initialSize):连接池初始化时创建的连接数。
  2. 最大连接数(maxActive):连接池中最大的连接数,也就是连接池所能容纳的最大连接数量,当连接池中的连接数量达到此值时,后续请求会被阻塞并等待连接池中有连接被释放后再处理。
  3. 最小空闲连接数量(minIdle): 指连接池中最小的空闲连接数,也就是即使当前没有请求,连接池中至少也要保持一定数量的空闲连接,以便应对高并发请求或突发连接请求的情况。
  4. 最大空闲连接数量(maxIdle): 指连接池中最大的空闲连接数,也就是连接池中最多允许保持的空闲连接数量。当连接池中的空闲连接数量达到了maxIdle设定的值后,多余的空闲连接将会被连接池释放掉。
  5. 最大等待时间(maxWait):当连接池中的连接数量达到最大值时,后续请求需要等待的最大时间,如果超过这个时间,则会抛出异常。
  6. 连接有效性检查(testOnBorrow、testOnReturn):为了确保连接池中只有可用的连接,一些连接池会定期对连接进行有效性检查,这里的属性就是配置这些检查的选项。
  7. 连接的driver、url、user、password等。

以上这些属性是连接池中较为常见的一些属性,不同的连接池在实现时可能还会有其他的一些属性,不过大多数连接池都包含了以上几个属性,对于使用者来说需要根据自己的需要进行灵活配置。

常用的连接池

市面上常用的数据库连接池有许多,以下是其中几种:3,4用的比较多

  1. DBCP
    1. 2001年诞生,最早的连接池。
    2. Apache Software Foundation的一个开源项目。
    3. DBCP的设计初衷是为了满足Tomcat服务器对连接池管理的需求。
  1. c3p0
    1. 2004年诞生
    2. c3p0是由Steve Waldman于2004年推出的,它是一个高性能、高可靠性、易配置的数据库连接池。c3p0能够提供连接池的容错能力、自动重连等功能,适用于高并发场景和数据量大的应用。
  1. Druid
    1. 2012年诞生
    2. Druid连接池由阿里巴巴集团开发,于2011年底开始对外公开,2012年正式发布。Druid是一个具有高性能、高可靠性、丰富功能的数据库连接池,不仅可以做连接池,还能做监控、分析和管理数据库,支持SQL防火墙、统计分析、缓存和访问控制等功能。
  1. HikariCP
    1. 2012年诞生
    2. HikariCP是由Brett Wooldridge于2012年创建的开源项目,它被认为是Java语言下最快的连接池之一,具有快速启动、低延迟、低资源消耗等优点。HikariCP连接池适用于高并发场景和云端应用。
    3. 很单纯的一个连接池,这个产品只做连接池应该做的,其他的不做。所以性能是极致的。相对于Druid来说,它更加轻量级。
    4. Druid连接池在连接管理之外提供了更多的功能,例如SQL防火墙、统计分析、缓存、访问控制等,适用于在数据库访问过程中,需要进行细粒度控制的场景
    5. HikariCP则更侧重于性能方面的优化,对各种数据库的兼容性也更好
  1. BoneCP
    1. 2015年诞生
    2. BoneCP是一款Java语言下的高性能连接池,于2015年由Dominik Gruntz在GitHub上发布。BoneCP具有分布式事务、连接空闲检查、SQL语句跟踪和性能分析、特定类型的连接池等特点。BoneCP连接池适用于大型应用系统和高并发的负载场景

连接池的使用

Druid的使用

第一步:引入Druid的jar包

第二步:配置文件在类的根路径下创建一个属性资源文件:jdbc.properties

url=jdbc:mysql://localhost:3306/jdbc
username=root
password=1234
driverClassName=com.mysql.cj.jdbc.Driver
initialSize=5
minIdle=10
maxActive=20

第三步:编写代码,从连接池中获取连接对象

// 读取属性配置文件
InputStream in = DruidConfig.class.getClassLoader().getResourceAsStream("jdbc.properties");
Properties props = new Properties();
props.load(in);
// 创建连接池
//获取连接池对象
DataSource dataSource = DruidDataSourceFactory.createDataSource(props);
//通过连接池对象获取连接对象
Connection conn = dataSource.getConnection();

第四步:关闭连接仍然调用Connection的close()方法,但是这个close()方法并不是真正的关闭连接,只是将连接归还到连接池,让其称为空闲连接对象。这样其他线程可以继续使用该空闲连接。

HikariCP的使用

第一步:引入jar包第二步:编写配置文件在类的根路径下创建一个属性资源文件:jdbc2.properties

jdbcUrl=jdbc:mysql://localhost:3306/jdbc
username=root
password=1234
driverClassName=com.mysql.cj.jdbc.Driver
minimumIdle=5
maximumPoolSize=20

第三步:编写代码,从连接池中获取连接

InputStream in = HikariConfig.class.getClassLoader().getResourceAsStream("config.properties");
props.load(in);
HikariConfig config = new HikariConfig(props);
//获取连接池对象
DataSource dataSource = new HikariDataSource(config);
通过连接池对象获取连接对象
Connection conn = dataSource.getConnection();

第四步:关闭连接(调用conn.close(),将连接归还到连接池,连接对象为空闲状态。)

改进

public class DbUtils2 {
    private DbUtils2(){}

    private static DataSource dataSource;

    static {
        try {
            InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream("jdbc.properties");
            Properties prop = new Properties();
            prop.load(in);
            dataSource = DruidDataSourceFactory.createDataSource(prop);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 获取数据库连接对象
     * @return 连接对象
     * @throws SQLException
     */
    public static Connection getConnection() throws SQLException {
        return dataSource.getConnection();
    }


    /**
     * 释放资源
     * @param conn 连接对象
     * @param stmt 数据库操作对象
     * @param rs 结果集对象
     */
    public static void close(Connection conn, Statement stmt, ResultSet rs){
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
        if (stmt != null) {
            try {
                stmt.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Java老狗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值