
「JavaWeb学习笔记02」数据库连接池
¶Chapter 2. 数据库连接池
¶2.1 引言
数据库连接池,负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个。
¶2.1.1 数据库连接池的原理
连接池基本思想是,在系统初始化的时候,将数据库连接作为对象存储在内存中,当用户需要访问数据库时,并非建立一个新的连接,而是从连接池中取出一个已建立的空闲连接对象。使用完毕后,用户也并发将连接关闭,而是将连接放回连接池中,以供下一个请求访问使用。而连接的建立、断开都由连接池自身来管理。
¶2.1.2 数据库连接池影响因素
数据库连接池在初始化时将创建一定数量的数据库连接放到连接池中,这些数据库连接的数量是由最小数据库连接数制约。无论这些数据库连接是否被使用,连接池都将一直保证至少拥有这么多的连接数量。
连接池的最大数据库连接数量限定了这个连接池能占有的最大连接数,当应用程序向连接池请求的连接数超过最大连接数量时,这些请求将被加入到等待队列中。
¶2.2 数据库连接技术
¶2.2.1 C3P0
¶步骤
- 不仅要导入数据库驱动 jar 包,还要导入 两个 jar 包(见下图,可去该网站查找下载)。
- 定义配置文件(文件名称为
c3p0.properties或者c3p0-config.xml),路径一般放在项目的src目录下。 - 创建核心对象——数据库连接池
DataSource对象——new一个ComboPooledDataSource - 调用该对象的方法以获取连接:
getConnection
¶使用举例

¶2.2.2 Druid (使用较多)
¶步骤
- 不仅要导入数据库驱动 jar 包,导入数据库连接池的 jar 包(见下图)
- 定义配置文件(任意名称、任意目录,前提是以
properties为文件名后缀 ) - 通过类加载器获取以配置文件为路径的文件流,然后调用
properties的方法来加载配置文件。 - 获取数据库连接池
DataSource对象—— 调用工厂类DruidDataSourceFactory的方法createDataSource - 调用该对象的方法以获取连接:
getConnection
¶使用举例

¶2.2.3 定义工具类 JDBCUtils
定义一个工具类 JDBCUtils,首先要通过静态代码块加载配置文件,初始化连接池对象。提供的方法应有:
- 通过数据库连接池对象获取连接对象
- 释放
PreparedStatement对象、ResultSet对象,归还 连接对象。
¶使用举例
工具类 JDBCUtils.java:
1 | |
演示测试类:DruidByUtils.java
1 | |
运行结果:

¶2.3 Spring JDBC
Spring 框架对 JDBC 进行了简单封装,提供了一个JDBCTemplate 对象简化了JDBC的开发。
❗ 自定义的类的成员变量,必须与 SQL 中的列名称相同,如此,才能够使用
queryForObject方法进行封装。
¶2.3.1 使用步骤
导入几个 jar 包(见下图)
创建
JdbcTemplate对象,依赖于 数据源对象DataSource调用
JdbcTemplate的相关方法来完成数据库的相关操作下面方法中参数
Object ... args为占位符?依次(即无需说明第几个)要填的参数update(String sql, Object ... args):执行 DML 语句完成数据库表中数据的增、删、改queryForMap(String sql, Object ... args):查询结果并将 结果集 封装为Map集合(列名作为key,值作为value)注意,该方法的查询结果集长度只能为 1
query(String sql, RowMapper<T> rowMapper):查询结果,将结果封装为JavaBean对象(一般我们使用BeanPropertyRowMapper实现类,来帮助我们将数据自动封装到我们自定义的JavaBean类对象)1
query(sql, new BeanPropertyRowMapper<自定义类>(自定义类.class))注意,若返回结果为单个元素,则直接返回对象;若返回结果为多个元素,则会返回以该对象为类型的
List,举例如下:1
2List<User> users = template.query(sql, new BeanPropertyRowMapper<User>(User.class)); //其中sql="SELECT * FROM USER";
User user = template,queryForObject(sql, new BeanPropertyRowMapper<User>(User.class), username, userpassword); //其中 sql = "SELECT * FROM userlist WHERE username = ? AND password = ?";queryForObject(String sql, Object[] args, Class<T> elementType):查询结果,并将结果封装为对象,常用于 聚合函数 的查询1
2
3
4public int findTotalCount(){
String sql = "SELECT COUNT(*) FROM userlist";
return template.queryForObject(sql, Integer.class);
} //Integer 自动拆箱为 int
¶简单使用举例(使用工具类 JdbcUtils )

¶2.3.3 执行DML、DQL
使用 JdbcUtils + Junit + Spring JDBC
提示:当使用
@Test出现红线时,应:
1 | |
建议使用两根手指将页面拉大~
test1() 运行结果 | test2() 运行结果 |
|---|---|
![]() | ![]() |
test3() 运行结果 | test4() 运行结果 |
|---|---|
![]() | ![]() |
test6() 运行结果 |
|---|
![]() |
¶2.3.4 组合查询的技巧
由于用户查询时,有可能不需要条件查询,有可能需要条件 1 查询,也有可能需要条件 2 查询 …
为了更好地维护,可以这样写:
定义并初始化 sql 字符串及相应的
StringBuilder(因为可能存在大量的拼接操作,详见 JavaSE 笔记)。1
2String sql = "SELECT COUNT(*) FROM user WHERE 1 = 1 "; //这里的 "WHERE 1 = 1" 用得十分妙
StringBuilder strB = new StringBuilder(sql);通过 HTTP 请求中携带的信息,获取条件查询的参数:
1
2
3Map<String, String[]> conditions = request.getParameterMap();
Set<String> keySet = conditions.keySet();
List<Object> params = new ArrayList<Object>();遍历
conditions,查看每个元素的key是否存在value,若有,则拼接到原来的 sql 字符串。格式统一,方便维护——sql.append("AND ? LIKE ?");1
2
3
4
5
6
7
8for(String key : keySet){
//根据key获取value
String[] value = condition.get(key)[0];
if(value != null && !"".equals(value)){
sb.append(" AND " + key + "LIKE ? ");
params.add("%" + value + "%");
}
}