数据库JDBC(连接池与DBUtils)

为什么要使⽤连接池 
⽬的:为了解决建⽴数据库连接耗费资源和时间很多的问题,提⾼性能。 Connection对象在JDBC使⽤的时候就会去创建⼀个对象,使⽤结束以后就会将这个对象给销毁了(close). 每次创建和销毁对象都是耗时操作.需要使⽤连接池对其进⾏优化.程序初始化的时候,初始化多个连接,将多个连接放⼊到池(集合)中.每次获取的时候,都可以直接从连接池 中进⾏获取.使⽤结束以后,将连接归还到池中. 

连接池原理:

1. 程序⼀开始就创建⼀定数量的连接,放在⼀个容器中,这个容器称为连接池(相当于碗柜/容器)。
2. 使⽤的时候直接从连接池中取⼀个已经创建好的连接对象。
3. 关闭的时候不是真正关闭连接,⽽是将连接对象再次放回到连接池中。

编写标准的数据源(规范)

Java为数据库连接池提供了公共的接⼝:javax.sql.DataSource,各个⼚商需要让⾃⼰的连接池实现这个接⼝。这样应⽤程序可以⽅便的切换不同⼚商的连接池!

常⻅的第三⽅(⾼性能)连接池如下:

  • C3P0开源免费的连接池!⽬前使⽤它的开源项⽬有:Spring、Hibernate等。使⽤C3P0连接池需要导⼊jar包,c3p0使⽤时还需要添加配置⽂件“c3p0-config.xml”
  • 功能全⾯的Druid:Druid是阿⾥巴巴开源平台上的⼀个项⽬,整个项⽬由数据库连接池、插件框架和SQL解析器组成。Druid是国内⽬前最好的数据库连接池,在功能、性能、扩展性⽅⾯,都超过其他数据库连接池(包括DBCP、C3P0、BoneCP、Proxool、JBoss DataSource)。Druid是阿⾥巴巴开发的号称为监控⽽⽣的数据库连接池!
  • 性能⽆敌的HikariCP:HikariCP是由⽇本程序员开源的⼀个数据库连接池组件,代码⾮常轻量,并且速度⾮常的快。根据官⽅提供的数据,在i7,开启32个线程32个连接的情况下,进⾏随机数据库读写操作,HikariCP的速度是现在常⽤的C3P0数据库连接池的数百倍。在SpringBoot2.0中,官⽅也是推荐使⽤HikariCP。

C3P0连接池

C3P0开源免费的连接池!⽬前使⽤它的开源项⽬有:Spring、Hibernate等。使⽤C3P0连接池需要导⼊jar包,c3p0使⽤时还需要添加配置⽂件“c3p0-config.xml”

C3P0连接池⼯具类编写

使⽤步骤
1. 导⼊c3p0-0.9.1.2.jar
2. 拷⻉配置⽂件到src⽬录
3. 创建连接池(配置⽂件⾃动读取的)

  • 编写配置⽂件 c3p0-config.xml
<c3p0-config>
    <!-- 使⽤默认的配置读取连接池对象 -->
    <default-config>
        <!-- 连接参数 -->
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property
name="jdbcUrl">jdbc:mysql://localhost:3306/day19</property>
        <property name="user">root</property>
        <property name="password">root</property>
        <!-- 连接池参数 -->
        <property name="initialPoolSize">5</property>
    </default-config>
</c3p0-config>

c3p0连接池常⽤的配置参数:

参数 说明
initialPoolSize 初始连接数
maxPoolSize 最⼤连接数
checkoutTimeout 最⼤等待时间
maxIdleTime 最⼤空闲回收时间

初始连接数:刚创建好连接池的时候准备的连接数量
最⼤连接数:连接池中最多可以放多少个连接
最⼤等待时间:连接池中没有连接时最⻓等待时间
最⼤空闲回收时间:连接池中的空闲连接多久没有使⽤就会回收

编写Java代码

/**
* C3P0连接池的⼯具类
*
*/
public class C3P0Utils {
    //1. 创建⼀个C3P0的连接池对象(会⾃动读取src⽬录下的c3p0-config.xml,所以不需要我们解析配置⽂件)
    public static DataSource ds = new ComboPooledDataSource();
    //2. 提供 从连接池中 获取连接对象的⽅法
    public static Connection getConnection() throws SQLException {
        Connection conn = ds.getConnection();
        return conn;
    }
    //3. 提供 获得数据源(连接池对象)的⽅法
    public static DataSource getDataSource(){
        return ds;
    }
}

Druid 连接池

Druid是阿⾥巴巴开发的号称为监控⽽⽣的数据库连接池,Druid是国内⽬前最好的数据库连接池。在功能、性能、扩展性⽅⾯,都超过其他数据库连接池。Druid已经在阿⾥巴巴部署了超过600个应⽤,经过⼀年多⽣产环境⼤规模部署的严苛考验。如:⼀年⼀度的双⼗⼀活动,每年春运的抢⽕⻋票。
Druid的下载地址:https://github.com/alibaba/druid
DRUID连接池使⽤的jar包: druid-1.1.16.jar

Druid连接池⼯具类编写

步骤:
1. 导⼊DRUID jar 包
2. 拷⻉配置⽂件到src⽬录
3. 根据配置⽂件 创建连接池对象
4. 从连接池对象获得连接
实现:

创建druid.properties, 放在src⽬录下

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test_wensong?useUnicode=true&characterEncoding=UTF-8&useSSL=false&use&serverTimezone=Asia/Shanghai
username=root
password=root

编写Java代码

/**
* 阿⾥巴巴的连接池 Druid ⼯具类
*/
public class DruidUtils {
    /*
    1. 加载 druid.properties 配置⽂件
    2. 创建 Druid 连接池对象
    3. 提供 获得 连接池对象的⽅法
    4. 提供 从连接池中 获取连接对象Connection的 ⽅法
    */
public static DataSource ds = null;
    static {
        try {
            //1. 加载 druid.properties 配置⽂件
            InputStream is =DruidUtils.class.getClassLoader().getResourceAsStream("druid.properties");
            Properties prop = new Properties();
            prop.load(is);
            //2. 创建 Druid 连接池对象
            ds = DruidDataSourceFactory.createDataSource(prop);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /*
    3. 提供 获得 连接池对象的⽅法
    */
    public static DataSource getDataSource(){
        return ds;
    }
    /*
    4. 提供 从连接池中 获取连接对象Connection的 ⽅法
    */
    public static Connection getConnetion() throws SQLException {
        Connection conn = ds.getConnection();
        return conn;
    }
}

DBUtils

如果只使⽤JDBC进⾏开发,我们会发现冗余代码过多,为了简化JDBC开发,本案例我们讲采⽤apache commons组件⼀个成员:DBUtils。DBUtils就是JDBC的简化开发⼯具包。需要项⽬导⼊commons-dbutils-1.6.jar 才能够正常使⽤DBUtils⼯具。

链接:https://pan.baidu.com/s/18u47P95zzMC1rzCPhUoVhQ 提取码:jg8o 

DBUtils是java编程中的数据库操作实⽤⼯具,⼩巧简单实⽤。DBUtils封装了对JDBC的操作,简化了JDBC操作,可以少写代码。
Dbutils三个核⼼功能介绍

  • QueryRunner中提供对sql语句操作的API.
  • ResultSetHandler接⼝,⽤于定义select操作后,怎样封装结果集.
  • DbUtils类,它就是⼀个⼯具类,定义了关闭资源与事务处理的⽅法

准备数据

创建表:

create table product(
    pid int primary key,
    pname varchar(20),
    price double,
    category_id varchar(32)
);

插⼊表记录

INSERT INTO product(pid,pname,price,category_id) VALUES(1,'联想',5000,'c001');
INSERT INTO product(pid,pname,price,category_id) VALUES(2,'海尔',3000,'c001');
INSERT INTO product(pid,pname,price,category_id) VALUES(3,'雷神',5000,'c001');
INSERT INTO product(pid,pname,price,category_id) VALUES(4,'JACKJONES',800,'c002');
INSERT INTO product(pid,pname,price,category_id) VALUES(5,'真维斯',200,'c002');
INSERT INTO product(pid,pname,price,category_id) VALUES(6,'花花公⼦',440,'c002');
INSERT INTO product(pid,pname,price,category_id) VALUES(7,'劲霸',2000,'c002');
INSERT INTO product(pid,pname,price,category_id) VALUES(8,'⾹奈⼉',800,'c003');
INSERT INTO product(pid,pname,price,category_id) VALUES(9,'相宜本草',200,'c003');
INSERT INTO product(pid,pname,price,category_id) VALUES(10,'⾯霸',5,'c003');
INSERT INTO product(pid,pname,price,category_id) VALUES(11,'好想你枣',56,'c004');
INSERT INTO product(pid,pname,price,category_id) VALUES(12,'⾹飘飘奶茶',1,'c005');
INSERT INTO product(pid,pname,price,category_id) VALUES(13,'果9',1,NULL);

QueryRunner核心类介绍

提供数据源

  • 构造⽅法
    • QueryRunner(DataSource) 创建核⼼类,并提供数据源,内部⾃⼰维护Connection
  • 普通⽅法
    • update(String sql , Object ... params) 执⾏DML语句
    • query(String sql , ResultSetHandler , Object ... params) 执⾏DQL语句,并将查询结果封装到对象中。

提供连接

  • 构造⽅法
    • QueryRunner() 创建核⼼类,没有提供数据源,在进⾏具体操作时,需要⼿动提供Connection
  • 普通⽅法
    • update(Connection conn , String sql , Object ... params) 使⽤提供的Connection,完成DML语句
    • query(Connection conn , String sql , ResultSetHandler , Object ...params) 使⽤提供的Connection,执⾏DQL语句,并将查询结果封装到对象中。

QueryRunner实现添加、更新、删除操作

update(String sql, Object... params) ⽤来完成表数据的增加、删除、更新操作

添加

// 插⼊数据
@Test
public void test1() throws SQLException {
    //1. 获取 QueryRunnr对象, 这个⽤于执⾏ Sql语句
    QueryRunner qr = new QueryRunner(DruidUtils.getDataSource());
    //2. 执⾏sql代码
    String sql = "insert into product values(?,?,?,?)";
    int line = qr.update(sql, 14, "康师傅⽅便⾯", 5, "c005");
    //3. 处理查询结果数据 ( 如果是插⼊, 更新, 删除操作 没有必要做 步骤3)
    System.out.println("line = " + line);
}

更新

// 更新数据
@Test
public void test2() throws SQLException {
    //1. 获取 QueryRunnr对象, 这个⽤于执⾏ Sql语句
    QueryRunner qr = new QueryRunner(DruidUtils.getDataSource());
    //2. 执⾏sql代码
    String sql = "update product set pname=? , price=? where pid=?";
    int line = qr.update(sql, "统⼀⽅便⾯", 4.5, 14);
    //3. 处理查询结果数据 ( 如果是插⼊, 更新, 删除操作 没有必要做 步骤3)
    System.out.println("line = " + line);
}

删除

// 删除数据
@Test
public void test3() throws SQLException {
    QueryRunner qr = new QueryRunner(DruidUtils.getDataSource());
    String sql = "delete from product where pid = ?";
    int line = qr.update(sql, 14);
    System.out.println("line = " + line);
}

QueryRunner实现查询操作

query(String sql, ResultSetHandler<T> rsh, Object... params) ⽤来完成表数据的查询操作

ResultSetHandler 结果集

  • BeanHandler:将结果集中第⼀条记录封装到⼀个指定的javaBean中。
  • BeanListHandler:将结果集中每⼀条记录封装到指定的javaBean中,将这些javaBean在封装到List集合中
  • ScalarHandler:它是⽤于单数据。例如select count(*) from 表操作。
  • ColumnListHandler:将结果集中指定的列的字段值,封装到⼀个List集合中

JavaBean

JavaBean就是⼀个类,在开发中常⽤语封装数据。具有如下特性
1. 需要实现接⼝:java.io.Serializable ,通常实现接⼝这步骤省略了,不会影响程序。
2. 提供私有字段:private 类型 字段名;
3. 提供getter/setter⽅法:
4. 提供⽆参构造

public class Product {
    private int pid;
    private String pname;
    private Double price;
    private String category_id;
    //省略 getter和setter⽅法
}

BeanHandler

/*
* 查询数据表结果集处理其中⼀种⽅式:
* BeanHandler处理⽅式
* 将数据表的结果集第⼀⾏数据,封装成JavaBean类的对象
* 构造⽅法:
* BeanHandler(Class<T> type)
* 传递⼀个Class类型对象,将结果封装到哪个类的对象呢
* Product类的Class对象
*/
@Test
public void demo01() throws SQLException{
    // 通过id查询详情,将查询结果封装到JavaBean product
    //1核⼼类    
    QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());
    //2 sql语句
    String sql = "select * from product where pid = ?";
    //3 实际参数
    Object[] params = {6};
    //4 查询并封装
    Product product = queryRunner.query(sql, new BeanHandler<Product>(Product.class), params);
    System.out.println(product);
}

BeanListHandler

/*
* 查询数据表结果集处理其中⼀种⽅式:
* BeanListHandler处理⽅式
* 将数据表的每⼀⾏数据,封装成JavaBean类对象
* 多⾏数据了,多个JavaBean对象,存储List集合
*/
@Test
public void demo02() throws SQLException{
    //查询所有,将每⼀条记录封装到⼀个JavaBean,然后将JavaBean添加到List中,最后返回List,BeanListHandler
    QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());
    String sql = "select * from product";
    Object[] params = {};
    List<Product> list = queryRunner.query(sql, new
    BeanListHandler<Product>(Product.class), params);
    for(Product product : list){
        System.out.println(product);
    }
}

ScalarHander

/*
* 查询数据表结果集处理其中⼀种⽅式:
* ScalarHandler处理⽅式
* 处理单值查询结果,执⾏的select语句后,结果集只有1个
*/
@Test
public void demo03() throws SQLException{
    // ScalarHandler : ⽤于处理聚合函数执⾏结果(⼀⾏⼀列)
    // * 查询总记录数
    QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());
    String sql = "select count(*) from product";
    Long obj = queryRunner.query(sql, new ScalarHandler<Long>());
    //System.out.println(obj.getClass());
    System.out.println(obj);
}

ColumnListHandler

/*
* 查询数据表结果集处理其中⼀种⽅式:
* ColumnListHandler处理⽅式
* 将查询数据表结果集中的某⼀列数据,存储到List集合
* 哪个列不清楚,数据类型也不清楚, List<Object>
* ColumnListHandler构造⽅法
* 空参数: 获取就是数据表的第⼀列
* int参数: 传递列的顺序编号
* String参数: 传递列名
*
* 创建对象,可以加⼊泛型,但是加⼊的数据类型,要和查询的列类型⼀致
*/
@Test
public void demo04() throws SQLException{
    // ColumnListHandler : 查询指定⼀列数据
    QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());
    String sql = "select * from product";
    List<String> list = queryRunner.query(sql, new ColumnListHandler<String>("pname"));
    System.out.println(list);
}

小结

DBUtils⼯具

  • 作⽤:简化JDBC的操作

DBUtils常⽤类与⽅法

  • QueryRunner构造⽅法
    • QueryRunner(DataSource) 创建核⼼类,并提供数据源,内部⾃⼰维护Connection
    • QueryRunner() 创建核⼼类,没有提供数据源,在进⾏具体操作时,需要⼿动提供Connection
  • QueryRunner ⽤来执⾏SQL语句对象
    • update(String sql , Object ... params) 执⾏DML语句
    • update(Connection conn, String sql, Object… params) 插⼊表记录、更新表记录、删除表记录
    • query(String sql , ResultSetHandler , Object ... params) 执⾏DQL语句,并将查询结果封装到对象中。
    • query(Connection conn, String sql, ResultSetHandler handler, Object…params) 查询表记录
  • ResultSetHandler 处理结果集的对象
    • BeanHandler:将结果集中第⼀条记录封装到⼀个指定的javaBean中。
      • BeanHandler<Product>(Product.class) --> Proudct
    • BeanListHandler:将结果集中每⼀条记录封装到指定的javaBean中,将这些javaBean在封装到List集合中
      • BeanListHandler<Product>(Product.class) --> List<Product>
    • ScalarHandler:它是⽤于单数据。例如select count(*) from 表操作。
      • ScalarHandler<Long>() --> Long
    • ColumnListHandler:将结果集中指定的列的字段值,封装到⼀个List集合中
      • ColumnListHandler<String>("pname") --> List<String>

猜你喜欢

转载自blog.csdn.net/weixin_40959890/article/details/107747573