Java - 数据库连接池 October 15,2019

## 数据库连接池

1. 概念:其实就是一个容器 (集合),存放数据库连接的容器。
    当系统初始化好后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库时,从容器中获取连接对象,用户访问完之后,会将连接对象归还给容器。

2. 好处:
    1. 节约资源。
    2. 用户访问高效。

3. 实现:
    1. 标准接口:DataSource javax.sql 包下的
    1. 方法:
        * 获取连接:getConnection()。
        * 归还连接:Connection.close()。如果连接对象 Connection 是从连接池中获取的,那么调用 Connection.close() 方法,则不会再关闭连接了,而是归还连接。

    2. 一般我们不去实现它,有数据库厂商来实现
        1. C3P0:数据库连接池技术
        2. Druid:数据库连接池实现技术,由阿里巴巴提供的

4. C3P0:数据库连接池技术
  * 步骤:
    1. 导入 jar 包 (两个)

      *c3p0-0.9.5.2.jar  与  mchange-commons-java-0.2.12.jar
      * 导入数据库驱动 jar 包 mysql-connector-java-5.1.37-bin.jar
    2. 定义配置文件:
      * 名称: c3p0.properties 或者 c3p0-config.xml
      * 路径:直接将文件放在 src 目录下即可。

    3. 创建核心对象 数据库连接池对象 ComboPooledDataSource
    4. 获取连接: getConnection
      * 代码:
        //1. 创建数据库连接池对象
          DataSource ds = new ComboPooledDataSource();
        //2. 获取连接对象
          Connection conn = ds.getConnection();
5. Druid:数据库连接池实现技术,由阿里巴巴提供的
  1. 步骤:
    1. 导入 jar 包

      * druid-1.0.9.jar

      * 导入数据库驱动 jar 包 mysql-connector-java-5.1.37-bin.jar
    2. 定义配置文件:
      * 是 properties 形式的
      * 可以叫任意名称,可以放在任意目录下

//druid.properties 文件内容
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql:///test?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false
username=root
password=123456
initialSize=5
maxActive=10
maxWait=3000

    3. 加载配置文件。Properties
    4. 获取数据库连接池对象:通过工厂来来获取 DruidDataSourceFactory
    5. 获取连接:getConnection
      * 代码:
      //1. 加载配置文件
        Properties pro = new Properties();
        InputStream is = DruidDemo.class.getClassLoader().getResourceAsStream("druid.properties");
        pro.load(is);
      //2. 获取连接池对象
        DataSource ds = DruidDataSourceFactory.createDataSource(pro);
      //3. 获取连接
        Connection conn = ds.getConnection();

import c3p0_druid.utils.JDBCUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class DruidDemo2 {
public static void main(String[] args) {
Connection connection
= null;
PreparedStatement preparedStatement
= null;
try {
//1. 获取连接对象
connection = JDBCUtils.getConnection();
//2. 定义 sql 语句
String sql = "insert into test values(null,?,?)";
//3. 获取 preparedStatement 对象
preparedStatement = connection.prepareStatement(sql);
//4. 赋值
preparedStatement.setString(1,"王五");
preparedStatement.setFloat(
2,3000);
//5. 执行 sql
int count = preparedStatement.executeUpdate();
System.out.println(count);
}
catch (SQLException e) {
e.printStackTrace();
}
finally {
//6. 释放资源
JDBCUtils.close(preparedStatement,connection);
}
}
}

  2. 定义工具类
    1. 定义一个类 JDBCUtils
    2. 提供静态代码块加载配置文件,初始化连接池对象
    3. 提供方法
      1. 获取连接方法:通过数据库连接池获取连接
      2. 释放资源方法
      3. 获取连接池的方法

//JDBCUtils 代码
import
com.alibaba.druid.pool.DruidDataSourceFactory; import javax.sql.DataSource; import java.io.IOException; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; /* * 工具类 * */ public class JDBCUtils {
</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> DataSource ds;
</span><span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)">{
    </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">1.加载配置文件</span>
        Properties properties = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Properties();
        properties.load(JDBCUtils.</span><span style="color: rgba(0, 0, 255, 1)">class</span>.getClassLoader().getResourceAsStream("druid.properties"<span style="color: rgba(0, 0, 0, 1)">));
       </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">2.获取DataSource</span>
        ds =<span style="color: rgba(0, 0, 0, 1)"> DruidDataSourceFactory.createDataSource(properties);
    } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (IOException e) {
        e.printStackTrace();
    } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (Exception e) {
        e.printStackTrace();
    }
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取连接方法</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> Connection getConnection() <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> SQLException {
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> ds.getConnection();
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">释放资源</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> close(Statement statement,Connection connection){
        close(</span><span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">,statement,connection);
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> close(ResultSet resultSet,Statement statement, Connection connection){
    </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
        </span><span style="color: rgba(0, 0, 255, 1)">if</span>(resultSet!=<span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
            resultSet.close();
        }
    } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (SQLException e) {
        e.printStackTrace();
    }

    </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
        </span><span style="color: rgba(0, 0, 255, 1)">if</span>(statement!=<span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
            statement.close();
        }
    } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (SQLException e) {
        e.printStackTrace();
    }

    </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
        </span><span style="color: rgba(0, 0, 255, 1)">if</span>(connection!=<span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
            connection.close();
        }
    } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (SQLException e) {
        e.printStackTrace();
    }
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取连接池方法</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> DataSource getDataSource(){
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> ds;
}

}

 

## Spring JDBC
* Spring 框架对 JDBC 的简单封装。提供了一个 JDBCTemplate 对象简化 JDBC 的开发
* 步骤:
  1. 导入 jar 包

    commons-logging-1.2.jar

    spring-beans-5.0.0.RELEASE.jar

    spring-core-5.0.0.RELEASE.jar

    spring-jdbc-5.0.0.RELEASE.jar

    spring-tx-5.0.0.RELEASE.jar

  2. 创建 JdbcTemplate 对象。依赖于数据源 DataSource

    * JdbcTemplate template = new JdbcTemplate(ds);

  3. 调用 JdbcTemplate 的方法来完成 CRUD 的操作
    * update(): 执行 DML 语句。增、删、改语句
    * queryForMap(): 查询结果将结果集封装为 map 集合,将列名作为 key,将值作为 value 将这条记录封装为一个 map 集合
      * 注意:这个方法查询的结果集长度只能是 1
    * queryForList(): 查询结果将结果集封装为 list 集合
      * 注意:将每一条记录封装为一个 Map 集合,再将 Map 集合装载到 List 集合中
    * query(): 查询结果,将结果封装为 JavaBean 对象
    * query 的参数:RowMapper
      * 一般我们使用 BeanPropertyRowMapper 实现类。可以完成数据到 JavaBean 的自动封装
      * new BeanPropertyRowMapper< 类型 >(类型.class)
    * queryForObject:查询结果,将结果封装为对象
      * 一般用于聚合函数的查询

import c3p0_druid.utils.JDBCUtils;
import org.springframework.jdbc.core.JdbcTemplate;

public class JDBCTemplate {
public static void main(String[] args) {
//1. 导入 jar 包
//2. 创建 JDBCTemplate 对象
JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
//3. 调用方法
String sql = "update test set banlance = 1000 where id = ?";
int count = template.update(sql,3);
System.out.println(count);
}
}

 

* 练习:

1. 修改 1 号数据的 salary 为 10000
2. 添加一条记录
3. 删除刚才添加的记录
4. 查询 id 为 1 的记录,将其封装为 Map 集合
5. 查询所有记录,将其封装为 List
6. 查询所有记录,将其封装为 Emp 对象的 List 集合
7. 查询总记录数