一、数据库连接池:就是为数据库连接建立一个“缓冲池”。预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去。
说白了就是提高效率。
二、作用:负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个。
三、工作原理:
数据库连接池在初始化时将创建一定数量的数据库连接放到连接池中。
这些数据库连接的数量是由最小数据库连接数来设定的。无论这些数据库连接是否被使用,连接池都将一直保证至少拥有这么多的连接数量。
连接池的最大数据库连接数量限定了这个连接池能占有的最大连接数,当应用程序向连接池请求的连接数超过最大连接数量时,这些请求将被加入到等待队列中。
四、数据库优点:
1. 资源重用
由于数据库连接得以重用,避免了频繁创建,释放连接引起的大量性能开销。在减少系统消耗的基础上,另一方面也增加了系统运行环境的平稳性。
2. 更快的系统反应速度
数据库连接池在初始化过程中,往往已经创建了若干数据库连接置于连接池中备用。此时连接的初始化工作均已完成。对于业务请求处理而言,直接利用现有可用连接,避免了数据库连接初始化和释放过程的时间开销,从而减少了系统的响应时间
3. 新的资源分配手段
对于多应用共享同一数据库的系统而言,可在应用层通过数据库连接池的配置,实现某一应用最大可用数据库连接数的限制,避免某一应用独占所有的数据库资源
4. 统一的连接管理,避免数据库连接泄漏
在较为完善的数据库连接池实现中,可根据预先的占用超时设定,强制回收被占用连接,从而避免了常规数据库连接操作中可能出现的资源泄露
五、多种数据库连接池
- DBCP 是Apache提供的数据库连接池。tomcat 服务器自带dbcp数据库连接池。速度相对c3p0较快,但因自身存在BUG,Hibernate3已不再提供支持。
- C3P0 是一个开源组织提供的一个数据库连接池,速度相对较慢,稳定性还可以。hibernate官方推荐使用
- Proxool 是sourceforge下的一个开源项目数据库连接池,有监控连接池状态的功能,稳定性较c3p0差一点
- BoneCP 是一个开源组织提供的数据库连接池,速度快
- Druid 是阿里提供的数据库连接池,据说是集DBCP 、C3P0 、Proxool 优点于一身的数据库连接池,但是速度不确定是否有BoneCP快
- DataSource 通常被称为数据源,它包含连接池和连接池管理两个部分,习惯上也经常把 DataSource 称为连接池
现在在实际代码工作中,一般都使用Druid方式。这里就单独介绍Druid连接池方式
这几种都可以采用XMl和配置文件方式
Druid
创建配置文件连接方式:
url=jdbc:mysql://localhost:3307/test?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8 username=root password=root123.. driverClassName=com.mysql.jdbc.Driver initialSize=10 maxActive=10
?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8
用来转换字节码,mysql是utf-8,idea也必须是utf-8 如果idea跟mysql字节码格式匹配那么就不需要
主要将url、useUnicode、username、password必须存在配置文件中。
initialSize | 0 | 初始化时建立物理连接的个数。初始化发生在显示调用init方法,或者第一次getConnection时 |
maxActive | 8 | 最大连接池数量 |
maxIdle | 8 | 已经不再使用,配置了也没效果 |
minIdle | 最小连接池数量 |
既然创建了链接,那么肯定要进行CRUD操作。 为了提高效率,Apache组织提供了方便的工具类
六、DBUtils工具类
6.1 DBUtils:
- commons-dbutils 是 Apache 组织提供的一个开源 JDBC工具类库,它是对JDBC的简单封装,学习成本极低,并且使用dbutils能极大简化jdbc编码的工作量,同时也不会影响程序的性能。
6.2 API的使用
主要使用QueryRunner和ResultSetHandler接口。
6.2.2 QueryRunner进行
介绍:该类简单化了SQL查询,它与ResultSetHandler组合在一起使用可以完成大部分的数据库操作,能够大大减少编码量。
- QueryRunner类提供了两个构造器:
- 默认的构造器
- 需要一个 javax.sql.DataSource 来作参数的构造器
- QueryRunner类的主要方法:
- 更新
- public int update(Connection conn, String sql, Object... params) throws SQLException:用来执行一个更新(插入、更新或删除)操作。
- ......
- 插入
- public <T> T insert(Connection conn,String sql,ResultSetHandler<T> rsh, Object... params) throws SQLException:只支持INSERT语句,其中 rsh - The handler used to create the result object from the ResultSet of auto-generated keys. 返回值: An object generated by the handler.即自动生成的键值
- ....
- 批处理
- public int[] batch(Connection conn,String sql,Object params)throws SQLException: INSERT, UPDATE, or DELETE语句
- public <T> T insertBatch(Connection conn,String sql,ResultSetHandler<T> rsh,Object params)throws SQLException:只支持INSERT语句
- .....
- 查询
- public Object query(Connection conn, String sql, ResultSetHandler rsh,Object... params) throws SQLException:执行一个查询操作,在这个查询中,对象数组中的每个元素值被用来作为查询语句的置换参数。该方法会自行处理 PreparedStatement 和 ResultSet 的创建和关闭。
如果要进行查询就要引入ResultSetHandler
6.2.3 ResultSetHandler进行各种查询操作
- 该接口用于处理 java.sql.ResultSet,将数据按要求转换为另一种形式。
- ResultSetHandler 接口提供了一个单独的方法:Object handle (java.sql.ResultSet .rs)。
- 接口的主要实现类:
- ArrayHandler:把结果集中的第一行数据转成对象数组。
- ArrayListHandler:把结果集中的每一行数据都转成一个数组,再存放到List中。
- BeanHandler:将结果集中的第一行数据封装到一个对应的JavaBean实例中。
- BeanListHandler:将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List里。
- ColumnListHandler:将结果集中某一列的数据存放到List中。
- KeyedHandler(name):将结果集中的每一行数据都封装到一个Map里,再把这些map再存到一个map里,其key为指定的key。
- MapHandler:将结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值。
- MapListHandler:将结果集中的每一行数据都封装到一个Map里,然后再存放到List
- ScalarHandler:查询单个值对象。
实例:
QueryInformation实体类
package com.Auto.CRUD;
import java.util.Date;
/**
* Created with IntelliJ IDEA.
*
* @Author: 王嘉辉
* @Date: 2021/12/23/10:20
* @Description: 一生一世为社会做贡献!
*/
public class QueryInformation {
private int id;
private String name;
private String email;
private Date birth;
public QueryInformation() {}
public QueryInformation(int id, String name, String email, Date birth) {
this.id = id;
this.name = name;
this.email = email;
this.birth = birth;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
}
@Override
public String toString() {
return "QueryInformatica{" +
"id=" + id +
", name='" + name + '\'' +
", email='" + email + '\'' +
", birth=" + birth +
'}';
}
}
查询方法:
/**
* 查询语句
* **BeanHandler:**将结果集中的第一行数据封装到一个对应的JavaBean实例中。
*/
@Test
public void testQuery() {
Connection conn=null;
try{
QueryRunner qr = new QueryRunner();
conn = JdbcUtils.connectionDruid();
String sql = "select*from customers where id =?";
BeanHandler<QueryInformation> handler = new BeanHandler<>(QueryInformation.class);
BeanListHandler<QueryInformation> handler1 = new BeanListHandler<>(QueryInformation.class);
QueryInformation qi = qr.query(conn, sql, handler, 21);
System.out.println(qi);
} catch (Exception e) {
e.printStackTrace();
} finally{
JdbcUtils.closeResource(conn,null);
}
}
/**
* 查询多条语句
* **BeanListHandler:**将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List里。
*/
@Test
public void testQuery2() {
Connection conn=null;
try{
QueryRunner qr = new QueryRunner();
conn = JdbcUtils.connectionDruid();
String sql = "select*from customers where id =?";
BeanListHandler<QueryInformation> handler1 = new BeanListHandler<>(QueryInformation.class);
List<QueryInformation> qi = qr.query(conn, sql, handler1, 21);
qi.forEach(System.out::println);
}catch (Exception e) {
e.printStackTrace();
} finally{
JdbcUtils.closeResource(conn,null);
}
}
/** 查询多条语句 MapHandler将结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值。 */
@Test
public void testQuery3() {
Connection conn = null;
try {
QueryRunner qr = new QueryRunner();
conn = JdbcUtils.connectionDruid();
String sql = "select*from customers where id =?";
MapHandler mh = new MapHandler();
Map<String, Object> qi = qr.query(conn, sql, mh, 21);
System.out.println(qi);
} catch (Exception e) {
e.printStackTrace();
} finally {
JdbcUtils.closeResource(conn, null);
}
}
/**
* 查询多条语句
* **MapListHandler:**将结果集中的每一行数据都封装到一个Map里,然后再存放到List
*/
@Test
public void testQuery4() {
Connection conn=null;
try{
QueryRunner qr = new QueryRunner();
conn = JdbcUtils.connectionDruid();
String sql = "select*from customers where id =?";
MapListHandler mlh = new MapListHandler();
List< Map<String, Object>> qi = qr.query(conn, sql, mlh, 21);
qi.forEach(System.out::println);
}catch (Exception e) {
e.printStackTrace();
} finally{
JdbcUtils.closeResource(conn,null);
}
}
/**
* 查询特殊操作(查询个数)
*
* **ScalarHandler:**查询单个值对象
*/
@Test
public void testQuery5() {
Connection conn=null;
try{
QueryRunner qr = new QueryRunner();
conn = JdbcUtils.connectionDruid();
String sql = "select count(*) from customers where id =?";
ScalarHandler sh = new ScalarHandler();
long qi = (long)qr.query(conn, sql, sh, 21);
System.out.println(qi);
}catch (Exception e) {
e.printStackTrace();
} finally{
JdbcUtils.closeResource(conn,null);
}
}
/**
*自定义resultSet实现类
*/
@Test
public void testQuery6() {
Connection conn=null;
try{
QueryRunner qr = new QueryRunner();
conn = JdbcUtils.connectionDruid();
String sql = "select*from customers where id =?";
ResultSetHandler<QueryInformation> rs = new ResultSetHandler<QueryInformation>() {
@Override
public QueryInformation handle(ResultSet resultSet) throws SQLException {
//查询结果返回null
return null;
}
};
QueryInformation qi = qr.query(conn, sql, rs, 21);
System.out.println(qi);
}catch (Exception e) {
e.printStackTrace();
} finally{
JdbcUtils.closeResource(conn,null);
}
}
}
看不懂就去B站学
七、JDBC总结
总结
@Test
public void testUpdateWithTx() {
Connection conn = null;
try {
//1.获取连接的操作(
//① 手写的连接:JDBCUtils.getConnection();
//② 使用数据库连接池:C3P0;DBCP;Druid
//2.对数据表进行一系列CRUD操作
//① 使用PreparedStatement实现通用的增删改、查询操作(version 1.0 \ version 2.0)
//version2.0的增删改public void update(Connection conn,String sql,Object ... args){}
//version2.0的查询 public <T> T getInstance(Connection conn,Class<T> clazz,String sql,Object ... args){}
//② 使用dbutils提供的jar包中提供的QueryRunner类
//提交数据
conn.commit();
} catch (Exception e) {
e.printStackTrace();
try {
//回滚数据
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
}finally{
//3.关闭连接等操作
//① JDBCUtils.closeResource();
//② 使用dbutils提供的jar包中提供的DbUtils类提供了关闭的相关操作
}
}