数据库连接池的好处

  1. 节约资源
  2. 高速访问
  3. 不必频繁的请求连接,释放连接等资源

实现

标准接口:DataSource

在javax.sql包下

  • 主要方法:
    1. 获取连接:getConnection()
    2. 归还连接:连接对象.close()会直接归还对象 而不是释放资源。

数据库厂商实现

  1. C3P0:c3p0是一个成熟的,高度并发的,开源JDBC连接池库,支持缓存和重用PreparedStatements。c3p0下载链接
  2. Druid:阿里数据库连接池技(号称全球最棒)。Druid不仅是一个数据库连接池,还包含一个ProxyDriver、一系列内置的JDBC组件库、一个SQL Parser。支持所有JDBC兼容的数据库,包括Oracle、MySql、Derby、Postgresql、SQL Server、H2等。
  3. dbcp:许多Apache项目使用。

1. C3P0

我学习的时候使用的c3p0-0.9.5.2版本。

怎么使用

根据官方文档说:Place the files lib/c3p0-0.9.5.2.jar and lib/mchange-commons-java-0.2.11.jar somewhere in your CLASSPATH (or any other place where your application’s classloader will find it). That’s it!
只要把相关的这两个jar包放在CLASSPATH或者用类加载器加载就行了。
(不要忘记导入数据库驱动jar包哦)

使用idea导入

直接建个libs之类的目录把jar包复制进去 然后右键选择add library

配置文件

定义

  • 使用java的java.util.Properties包配置c3p0.properties(键值对形式)
  • 使用xml配置:c3p0-config.xml
  • 通过HOCON(人工优化配置对象表示法)使用application.conf 或者 application.json 之类的配置

    路径

    在src目录下

    连接池核心对象

    ComboPooledDataSource
  • getConnection获取连接

示例C3P0

C3p0Test.class

1
2
3
4
5
//获取DataSource
DataSource dataSource = new ComboPooledDataSource("otherc3p0");
Connection connection = dataSource.getConnection();
//归还连接
connection.close();

c3p0-config.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<c3p0-config>
<!-- 使用默认的配置读取连接池对象 -->
<default-config>
<!-- 连接参数 -->
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/test</property>
<property name="user">root</property>
<property name="password">****</property>

<!-- 连接池参数 -->
<!--初始化申请的连接数量-->
<property name="initialPoolSize">5</property>
<!--最大的连接数量-->
<property name="maxPoolSize">10</property>
<!--超时时间-->
<property name="checkoutTimeout">3000</property>
</default-config>


//ComboPooledDataSource("otherc3p0")选择配置
<named-config name="otherc3p0">
<!-- 连接参数 -->
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/db3</property>
<property name="user">root</property>
<property name="password">root</property>

<!-- 连接池参数 -->
<property name="initialPoolSize">5</property>
<property name="maxPoolSize">8</property>
<property name="checkoutTimeout">1000</property>
</named-config>
</c3p0-config>

2. druid

配置文件

只需要导入一个jar包
druid的配置文件只有properties一种形式,可以是任意名称,任意目录

连接池

  • 获取连接池对象:使用工厂类 DruidDataSourceFactory
  • 其他通用一样

druid还提供了C3P0等数据库连接池的适配器。

示例Druid

DruidTest.class

1
2
3
4
5
6
7
Properties druidProperties = new Properties();
InputStream in = DruidTest.class.getClassLoader().getResourceAsStream("druid.properties");
druidProperties.load(in);
DataSource ds = DruidDataSourceFactory.createDataSource(druidProperties);
Connection conn = ds.getConnection();
conn.close();
System.out.println(ds);

打印DataSource对象会输出以下信息

1
2
3
4
5
6
7
8
9
10
11
12
{
4CreateTime:"2019-05-15 18:32:23",
4ActiveCount:0,
4PoolingCount:5,
4CreateCount:5,
4DestroyCount:0,
4CloseCount:1,
4ConnectCount:1,
4Connections:[
44{ID:2101842856, ConnectTime:"2019-05-15 18:32:24", UseCount:1, LastActiveTime:"2019-05-15 18:32:24"}
4]
}

druid.properties

1
2
3
4
5
6
7
8
9
10
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/test
username=root
password=****
# 初始化连接数
initialSize=5
# 最大连接数
maxActive=10
# 最长等待时间
maxWait=3000

3. spring jdbc

上述两种连接池使用起来还是比较麻烦,除了获取连接对象简单,其他操作还是一样的复杂。spring jdbc对jdbc进行了简单的封装。提供了JdbcTemplate

使用

  1. 依赖于5个jar包
  2. JdbcTemplate依赖于DataSource

    • new JdbcTemplate(Datasource)
  3. 使用JdbcTemplate的方法进行CRUD操作

    • updata() 执行DML语句,进行增,删,改操作
    • queryForMap() 查询结果,将结果封装为map集合
    • queryForList() 查询结果,将结果封装为list集合
    • query() 查询结果,将结果封装为JavaBean对象
    • queryForObject() 查询结果,将结果封装为对象
  4. 自动归还连接释放资源

spring jdbc依赖包
spring jdbc依赖包

JdbcTemplate.class

1
2
3
4
5
6
7
8
9
10
11
12
13
Properties druidProperties = new Properties();
InputStream in = DruidTest.class.getClassLoader().getResourceAsStream("druid.properties");
druidProperties.load(in);
//使用Druid获取DataSource,配置文件同Druid
DataSource ds = DruidDataSourceFactory.createDataSource(druidProperties);
JdbcTemplate template = new JdbcTemplate(ds);
//使用BeanPropertyRowMapper将查询结果自动封装进Music javaBean,再封装入List
//或者使用new RowMapper<Music>()重写方法,跟未封装的jdbc查询结果方式一样
String sql = "select * from singer";
List<MusicAuthor> query = template.query(sql, new BeanPropertyRowMapper<MusicAuthor>(MusicAuthor.class));
for (MusicAuthor author : query) {
System.out.println(author);
}

MusicAuthor这个javabean,只有String author;Integer age;两个属性

查询使用的数据库创建语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
CREATE DATABASE music;
use music;
CREATE TABLE singer(
4id_singer INT PRIMARY KEY auto_increment,
4author VARCHAR(20),
4age INT
);
CREATE TABLE song(
4id_song INT auto_increment,
4id_singer INT,
4song_name VARCHAR(40),
4release_time TIMESTAMP,
4PRIMARY KEY(id_song,id_singer),
4FOREIGN KEY(id_singer) REFERENCES singer(id_singer)
4
);

扩展阅读