JavaWeb基础篇(八)--JDBC连接池

一、连接池简介

1.数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个;释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏。

2.池参数(举例)

初始大小:10个

最小空闲连接数:3个

增量:一次创建的最小单位(5个)

最大空闲连接数:12个

最大连接数:20个

最大的等待时间:1000毫秒

3.需要掌握的数据库连接池

(1)C3P0:(常用)

(2)DBCP

二、自定义连接池

1.主要代码(简单演示,不严谨):

 

这里只是简单的实现了一个大致的流程,可以把 close方法增强,直接实现归还。 增强某个类中的某个方法,又称“装饰者模式”。

2.装饰者模式

步骤:

  . 继承     
  . 装饰者的模式(增强某接口的实现类(假设为cc)中的某个方法)
    * 增强的类(自己来写)和被增强的类(cc)必须实现相同的接口。
       * 在增强的类中能获取到被增强类的引用。
  . 动态代理

装饰者模式具体理解参考https://blog.csdn.net/ma598214297/article/details/80699377

3.自定义连接池较完善版的请参考:https://blog.csdn.net/u010452388/article/details/80210975

三、DBCP连接池

1.导入jar包

commons-dbcp2-2.5.0.jar

commons-pool2-2.6.1.jar

2.基本使用

 Connection conn = null;
 PreparedStatement stmt = null;
 ResultSet rs = null;
 DataSource dataSource = null;
 
 InputStream in = dbcpDemo.class.getClassLoader().getResourceAsStream("dbcp.properties");
 Properties pro = new Properties();
 try {
     pro.load(in);
 
     //获得数据源
     dataSource = BasicDataSourceFactory.createDataSource(pro);
     //获得链接
     conn = dataSource.getConnection();
 
     //编写sql语句
     String sql = "select * from person;";
     stmt = conn.prepareStatement(sql);
     rs = stmt.executeQuery();
 
     while (rs.next())
     {
         System.out.println(rs.getString("last_name"));
     }
 
 } catch (IOException e) {
     e.printStackTrace();
 } catch (Exception e) {
     e.printStackTrace();
 } finally {
     try {
         rs.close();
     } catch (SQLException e) {
         e.printStackTrace();
     }
     try {
         stmt.close();
     } catch (SQLException e) {
         e.printStackTrace();
     }
     try {
         conn.close();
     } catch (SQLException e) {
         e.printStackTrace();
     }
 }

3.遇到的问题:

(1)控制台报错

java.lang.AbstractMethodError: com.mysql.jdbc.Connection.isValid(I)Z

解决办法:更新MySQL驱动包的版本。

(2)控制台警告

Wed Mar 21 09:28:33 CST 2018 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.

解决办法:

修改数据库连接配置 dbcp.properties,加上useSSL=false即可
url = jdbc:mysql://localhost:3306/cm_sql?useUnicode=true&characterEncoding=UTF-8&useSSL=false

4.简单介绍几个其他的配置文件内容

initialSize=10    初始化连接

maxActive=50   最大连接数量

maxIdle=20     最大空闲连接

minIdle=5      最小空闲连接

maxWait=60000   超时等待时间以毫秒为单位 6000毫秒/1000等于60秒

defaultAutoCommit=true    指定由连接池所创建的连接的自动提交(auto-commit)状态。

四、c3p0连接池

1.导入jar包

c3p0-0.9.5.3.jar

mchange-commons-java-0.2.15.jar

2.基本使用

(1)配置文件,可以是peoperties文件,可以是xml文件。但是xml显得更高级一点。

配置文件举例

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
    <!-- 默认 -->
    <default-config>
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/cm_sql</property>
        <property name="user">root</property>
        <property name="password">miss</property>

        <!--初始化时获取三个连接,取值应在minPoolSize与maxPoolSize之间. -->
        <property name="initialPoolSize">5</property>
        <!--最大空闲时间,30秒内未使用则连接被丢弃。若为0则永不丢弃.-->
        <property name="maxIdleTime">30</property>
        <!--连接池中保留的最大连接数.-->
        <property name="maxPoolSize">10</property>
        <!--连接池中保留的最小连接数.-->
        <property name="minPoolSize">2</property>
        <!--用以控制数据源内加载的PreparedStatements数量 -->
        <property name="maxStatements">200</property>
    </default-config>


    <!-- 查找指定命名空间 -->
    <named-config name="mysql">
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/cm_sql</property>
        <property name="user">root</property>
        <property name="password">miss</property>
        <!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。-->
        <property name="acquireIncrement">3</property>
        <property name="initialPoolSize">5</property>
        <property name="minPoolSize">3</property>
        <property name="maxPoolSize">10</property>
        <property name="maxStatements">0</property>
        <property name="maxStatementsPerConnection">5</property>
    </named-config>

</c3p0-config>

(2)基本使用

Connection conn = null;
 PreparedStatement stmt = null;
 ResultSet rs = null;
 
 //默认去src下的c3p0-sonfig.xml文件
 ComboPooledDataSource cpds = new ComboPooledDataSource(); //不含参访问默认,含参数会查找指定命名空间的配置文件
 
 try {
     conn= cpds.getConnection();
 
     String sql = "select * from person;";
 
     stmt = conn.prepareStatement(sql);
     rs = stmt.executeQuery();
 
     while (rs.next())
     {
         System.out.println(rs.getString("first_name"));
     }
 
 } catch (SQLException e) {
     e.printStackTrace();
 } finally {
     try {
         rs.close();
     } catch (SQLException e) {
         e.printStackTrace();
     }
     try {
         stmt.close();
     } catch (SQLException e) {
         e.printStackTrace();
     }
     try {
         conn.close();
     } catch (SQLException e) {
         e.printStackTrace();
     }
 }

五、ThreadLocal与Connection

我们要保证Connection对每个请求都是唯一的.这个时候就可以用到ThreadLocal了,保证每个线程都有自己的连接。ThreadLocal类通过操作每一个线程特有的ThreadLocalMap副本,从而实现了变量访问在不同线程中的隔离。因为每个线程的变量都是自己特有的,完全不会有并发错误。
public static ThreadLocal<Connection> connectionThreadLocal = new ThreadLocal<Connection>();
//之后的连接都利用get方法从线程中获取。

猜你喜欢

转载自blog.csdn.net/weixin_43815050/article/details/87542159