Apache-DBUtils实现CRUD操作

Apache-DBUtils实现CRUD操作

在这里插入图片描述


每博一文案

有人说,不要轻易去伤害任何一个人,因为你会因此而受伤。欠的债,躲不掉,总是要还的。
要知道,哪些能被你欺骗的人,都是无条件相信你的人,因为心里有你,所以才会对你
一次又一次的迁就,因为不想让你受委屈,才愿意一直让你吗,你要珍惜每个对你好的人,
因为他本可以不这样做。人与人之间的感情就像一面镜子,一旦打破就,再难圆满了,
不要把别人对你的好心,当成理所当然,人心都是肉做的,受了冷落,都会疼。
不管一个人对你多好,一旦遭受欺骗,心会痛,也会寒心。
作家七堇年曾说:“这个世界上,真心对你好的人,遇到一个便少一个”。人海茫茫,我们遇到一个真心对我们
好的人,是一种幸运,没有谁的付出,是平白无故,没有谁会一直卑微地付出。
你懂得珍惜我,对你的好,我才会原意对你好。没有谁离不开谁,有的只是谁不珍惜谁,唯有
真心相待,关系才能长久,心一旦凉透了,就在也捂不热了。
人一旦弄丢了,就再也找不回了。辜负了别人是要还债的,辜负了自己是要遗憾终身的。
认识一个人不在于时间的长短,而在于彼此懂得和珍惜,人潮拥挤,相遇不易,
且行且珍惜,一个人时,专注自己,好好生活,有人爱时,有能力拥抱彼此,
愿你余生付出真心都有人珍惜,也不辜负每一个人信任的人。
                                            ——————   一禅心灵庙语


1. Apache-DBUtils 的介绍

commons-dbutils 是 Apache 组织提供的一个开源的 JDBC 工具类库,它是对 JDBC 的简单封装,学习成本比较低,并且使用 dbutils 能极大简化 jdbc 编码的工作量,同时也不会影响程序的性能。

API介绍:

API(Application Programming Interface,应用程序编程接口)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件的以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。API除了有应用“应用程序接口”的意思外,还特指 API的说明文档,也称为帮助文档。

相关的API 文件的说明:

  • org-apache.commons.dbutils.QueryRunner
  • org.apache.commons.dbutils.ResultSetHandler
  • 工具类:org.apache.commons.dbutils.DbUtils

使用其中的 DBUtils 我们需要相关的 commons-dbutils-1.3.jar 包,

在这里插入图片描述

jar 文件我们已经托管到了 ,Github ,Gitee 当中了,如有需要,大家可以自行下载


2. QueryRunner类

DbUtils 工具类当中,存在这么一个 QueryRunner 类,该类简单化了SQL查询,它与 ResultSetHandler 组合在一起使用可以完成大部分数据库操作,能够大大减少编码量。

QueryRunner 提供了两个构造器:

  1. 默认的构造器
  2. 需要一个 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 SQLExceptionINSERT, 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:执行一个查询操作,在这个查询中,对象数组中的每个元素值被用来作为查询语句的置换参数。该方法会自行处理 PreparedStatementResultSet 的创建和关闭。

具体其他更多的方法,大家可以查看我们 下载的 DbUtils 的帮助文档index.html ,在( commons-dbutils-1.3\apidocs )该路径下可以找到:

在这里插入图片描述

在这里插入图片描述


Commons-dbutils 中的 QueryRunner 类封装了针对于数据库的 增,删,改 DDL 操作。

这里我们连接数据库,使用 Druid 的数据库连接池,其中具体的详细内容,大家可以移步到 🔜🔜🔜 c3p0,DBCP,Druid(德鲁伊)数据库连接池_ChinaRainbowSea的博客-CSDN博客 观看

首先导入相关的 commons-dbutils-1.3.jar的包,在IDEA中 导入 jar 包,操作如下:

在这里插入图片描述


1. insert (插入)

使用 DbUtils 中的 QueryRunner类中的方法 为’customers’数据表 插入insert一条记录:
在这里插入图片描述

在这里插入图片描述

这里我们插入一条 “李华,985@qq.com,2022-11-23” 的记录信息

具体代码实现如下:

package Blogs.blogs04;

import com.alibaba.druid.pool.DruidDataSourceFactory;
import org.apache.commons.dbutils.QueryRunner;

import javax.sql.DataSource;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

public class QueryRunnerTest {
    public static void main(String[] args) {
        // 获取到配置文件的信息方式一: 这里获取到的是 druid数据库连接池中的配置文件的信息
        InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("druid.properties");  // 默认是src目录下的文件
        Connection connection = null;

        try {
            // 获取到配置文件的信息方式二:
            FileInputStream io = new FileInputStream(new File("src/druid.properties"));

            // 创建获取配置文件中的信息的对象
            Properties properties = new Properties();
            properties.load(io); // 以简单的线性格式输入字符读取属性列表(关键字/元素对)

            // 通过传入读取到配置文件对象,创建druid数据库连接池
            DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);

            // 获取到 druid数据库连接池中的其中的一个连接
            connection = dataSource.getConnection();

            // 使用 QueryRunner 插入记录
            QueryRunner queryRunner = new QueryRunner();

            String sql = "insert into customers(name,email,birth) values(?,?,?)"; // 占位符不要加单引号,不然就成了字符串了

            // 执行sql语句  connection 表示连接,sql 表示要执行的sql语句,params:表示填充占位符
            int insertCount = queryRunner.update(connection, sql, "李华", "985@qq.com", "2022-11-23"); // 返回影响数据库的行数

            System.out.println("添加了 "+insertCount+"条记录");
        } catch (Exception e) {
            throw new RuntimeException(e);  // 将编译异常转换为运行异常抛出
        } finally {
            if(connection != null) {
                try {
                    // 使用了数据库连接池中的连接,所以是 “归还连接”不是关闭连接
                    connection.close();
                } catch(SQLException e) {
                    throw new RuntimeException(e);  // 将编译异常转换为运行异常抛出

                }
            }
        }

    }

}

在这里插入图片描述

在这里插入图片描述


2. update(更新/修改)

使用 DbUtils 中的 QueryRunner类中的方法 为’customers’数据表 修改update一条记录:

这里我们将 cusomers 数据表中的 id 为 24 的 birth 修改为 “2000-1-1”

具体代码实现如下:

package Blogs.blogs04;

import com.alibaba.druid.pool.DruidDataSourceFactory;
import org.apache.commons.dbutils.QueryRunner;

import javax.sql.DataSource;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

public class QueryRunnerTest {
    public static void main(String[] args) {
        // 获取到配置文件的信息方式一: 这里获取到的是 druid数据库连接池中的配置文件的信息
        InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("druid.properties");  // 默认是src目录下的文件
        Connection connection = null;

        try {
            // 获取到配置文件的信息方式二:
            FileInputStream io = new FileInputStream(new File("src/druid.properties"));

            // 创建获取配置文件中的信息的对象
            Properties properties = new Properties();
            properties.load(io); // 以简单的线性格式输入字符读取属性列表(关键字/元素对)

            // 通过传入读取到配置文件对象,创建druid数据库连接池
            DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);

            // 获取到 druid数据库连接池中的其中的一个连接
            connection = dataSource.getConnection();

            // 使用 QueryRunner 插入记录
            QueryRunner queryRunner = new QueryRunner();

            String sql = "update customers set birth = ? where id = ?"; // 占位符不要加单引号,不然就成了字符串了

            // 执行sql语句                       connection 表示连接,sql 表示要执行的sql语句,params:表示填充占位符
            int insertCount = queryRunner.update(connection, sql, "2000-1-1",24); // 返回影响数据库的行数

            System.out.println("修改了 "+insertCount+"条记录");
        } catch (Exception e) {
            throw new RuntimeException(e);  // 将编译异常转换为运行异常抛出
        } finally {
            if(connection != null) {
                try {
                    // 使用了数据库连接池中的连接,所以是 “归还连接”不是关闭连接
                    connection.close();
                } catch(SQLException e) {
                    throw new RuntimeException(e);  // 将编译异常转换为运行异常抛出

                }
            }
        }


    }

}

在这里插入图片描述

在这里插入图片描述


3. delete(删除)

使用 DbUtils 中的 QueryRunner类中的方法 为’customers’数据表 删除delete一条记录:

这里我们删除 customers 数据表中 id 为 24 的记录

package Blogs.blogs04;

import com.alibaba.druid.pool.DruidDataSourceFactory;
import org.apache.commons.dbutils.QueryRunner;

import javax.sql.DataSource;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

public class QueryRunnerTest {
    public static void main(String[] args) {
        // 获取到配置文件的信息方式一: 这里获取到的是 druid数据库连接池中的配置文件的信息
        InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("druid.properties");  // 默认是src目录下的文件
        Connection connection = null;

        try {
            // 获取到配置文件的信息方式二:
            FileInputStream io = new FileInputStream(new File("src/druid.properties"));

            // 创建获取配置文件中的信息的对象
            Properties properties = new Properties();
            properties.load(io); // 以简单的线性格式输入字符读取属性列表(关键字/元素对)

            // 通过传入读取到配置文件对象,创建druid数据库连接池
            DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);

            // 获取到 druid数据库连接池中的其中的一个连接
            connection = dataSource.getConnection();

            // 使用 QueryRunner 插入记录
            QueryRunner queryRunner = new QueryRunner();

            String sql = "delete from customers where id = ?"; // 占位符不要加单引号,不然就成了字符串了

            // 执行sql语句                       connection 表示连接,sql 表示要执行的sql语句,params:表示填充占位符
            int insertCount = queryRunner.update(connection, sql, 24); // 返回影响数据库的行数

            System.out.println("删除了 "+insertCount+"条记录");
        } catch (Exception e) {
            throw new RuntimeException(e);  // 将编译异常转换为运行异常抛出
        } finally {
            if(connection != null) {
                try {
                    // 使用了数据库连接池中的连接,所以是 “归还连接”不是关闭连接
                    connection.close();
                } catch(SQLException e) {
                    throw new RuntimeException(e);  // 将编译异常转换为运行异常抛出

                }
            }
        }


    }

}

在这里插入图片描述

在这里插入图片描述


3. ResultSetHandler接口及实现类

DBUtils 中的 ResultSetYHandler 接口用于处理 java.sql.ResultSet 查询的结果集的处理,将查询到的结果集数据 按要求 转为为 另一种形成存储起来,比如:数组,链表,哈希、

ResultSetHandler 接口提供了一个单独的方法:Object handle ( java.sql. ResultSet.rs)

该 ResultSetHandler 接口的主要实现类: 有如下这些

  1. ArrayHandler :把 select 查询显示的结果集中的 第一行 数据转换为 对象数组存储起来。简单的说就是处理 select 查询的一条 记录

  2. ArrayListHandler :把 select 查询显示的结果集中的 所有每一行 数据都先转换为一个数组对象,再将这些转换好的数组对象,存储到 List 链表当中。简单的说就是处理 select 查询的 多条 记录

  3. BeanHandler :把 select 查询显示的结果集中的 第一行 数据封装存储到一个对应的 JavaBean(ORM映射类) 的实例对象当中去。

  4. BeanListHandler : 把 select 查询显示的结果集中的 所有每一行 数据都先封装存储到一个对应的 JavaBean(ORM映射类) 的实例对象当中去,再将这些 JavaBean实例对象,存放到 List 链表当中

  5. MapHandler : 把 select 查询显示的结果集中的 第一行 数据封装存储到一个 Map 里,key 是列名,value就是对应列名的值

  6. MapListHandler :把 select 查询显示的结果集中的 所有每一行 数据先封装存储到一个Map 里,然后再存放到 LIst 链表当中去。

  7. ColumnListHandler : select 查询显示的结果集中的 某一列 数据存放到 List 链表当中

  8. KeyedHandler(name) :把 select 查询显示的结果集中的 所有每一行 数据都先封装到一个Map 里,再把这些 map 又存放到一个 Map 里,其中 key 为指定的 key.

  9. ScalarHandler :查询单个特殊值的对象。如:count(), max(),sum()

在其 API 的帮助文档index.html 中可以找到上述类方法的详细介绍如下:

在这里插入图片描述

ResultSetHandler,此接口用于处理数据库查询 DQL 操作得到的结果集,不同的结果集的形式不同,由其不同的子类来实现。


说明以下:下面所有的 查询方法演示都是基于 customers 数据表的

在这里插入图片描述

在这里插入图片描述

首先创建相关的customers 数据表的 JavaBean实例(ORM映射)

一张数据表对应一个Java类,一个数据表中的一行记录对应 Java当中的一个对象,一个数据表中的字段/列值对应Java当中的一个属性。

package Blogs.blogs04;

import java.sql.Date;

public class Customer {
    private int id;
    private String name;
    private String email;
    private Date birth;
    
    public Customer() {
        // 必须创建一个无参的构造器,用于反射获取其中的属性赋值
    }

    public Customer(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 "Customer{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", email='" + email + '\'' +
                ", birth=" + birth +
                '}';
    }
}

1. ArrayHandler

ArrayHandler :把 select 查询显示的结果集中的 第一行 数据转换为 对象数组存储起来。简单的说就是处理 select 查询的一条 记录

具体代码实现如下:

package Blogs.blogs04;

import com.alibaba.druid.pool.DruidDataSourceFactory;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.ArrayHandler;

import javax.sql.DataSource;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.util.Arrays;
import java.util.Properties;

public class ResultSetHandler {
    public static void main(String[] args) {
        // 读取配置文件方式一:
        InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("druid.properties");  // 默认是读取src
        // 目录下的配置文件

        try {
            // 读取配置文件方式二:
            FileInputStream io = new FileInputStream(new File("src/druid.properties"));

            // 创建 Properties对象用于获取到以读取的配置信息参数
            Properties properties = new Properties();
            properties.load(io);   // 以简单的线性格式读取属性列表(关键字/元素对)
            // 通过传入读取配置文件的对象,创建 druid数据库连接池
            DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
            // 获取到 druid 数据库连接池中的连接
            Connection connection = dataSource.getConnection();


            // 创建存储 select 查询的存储方式:这里是 ArrayHandler 存储一条记录,以数组的形成存储起来
            ArrayHandler arrayHandler = new ArrayHandler();
            // 创建 QueryRunner 对象使用其中的 ResultSetHandler接口中的方法
            QueryRunner queryRunner = new QueryRunner();
            String sql = "select id,name,email,birth from customers where id = ?";   // 占位符不要加单引号,不然就成了字符串了
            // connection 连接,sql :sql语句,arrayHandler:存储形式,params 可变参数:填充占位符,可以不传参数,但不要传null
            Object[] arrs = queryRunner.query(connection, sql, arrayHandler, 10); // 执行sql语句,并处理select结果集
            System.out.println(Arrays.toString(arrs));  // 打印查询到的信息


            // 可以将创建存储形成,和执行sql,一体化 如下:
            Object[] query = queryRunner.query(connection, sql, new ArrayHandler(), 13);
            System.out.println(Arrays.toString(query));  // 打印查询到的信息


            // 没有查询到的返回null
            Object[] not = queryRunner.query(connection, sql, new ArrayHandler(), 100);
            System.out.println(Arrays.toString(not));  // 打印查询到的信息

        } catch (Exception e) {
            throw new RuntimeException(e);  // 将编译异常转换为运行异常抛出
        }
        

    }
}

在这里插入图片描述

2. ArrayListHandler

ArrayListHandler :把 select 查询显示的结果集中的 所有每一行 数据都先转换为一个数组对象,再将这些转换好的数组对象,存储到 List 链表当中。简单的说就是处理 select 查询的 多条 记录

具体代码如下:

import com.alibaba.druid.pool.DruidDataSourceFactory;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.ArrayListHandler;

import javax.sql.DataSource;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;

public class ResultSetHandler {
    public static void main(String[] args) {
        // 读取配置文件方式一:
        InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("druid.properties");  // 默认是读取src
        // 目录下的配置文件


        try {
            // 读取配置文件方式二:
            FileInputStream io = new FileInputStream(new File("src/druid.properties"));

            // 创建 Properties对象用于获取到以读取的配置信息参数
            Properties properties = new Properties();
            properties.load(io);   // 以简单的线性格式读取属性列表(关键字/元素对)
            // 通过传入读取配置文件的对象,创建 druid数据库连接池
            DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
            // 获取到 druid 数据库连接池中的连接
            Connection connection = dataSource.getConnection();


            // 创建存储 select 查询的存储方式:这里是  ArrayListHandler 存储 "多条" 记录,以数组的形式存储起来单条记录,再存入到List链表当中
            ArrayListHandler arrayListHandler = new ArrayListHandler();
            // 创建 QueryRunner 对象使用其中的 ResultSetHandler接口中的方法
            QueryRunner queryRunner = new QueryRunner();
            String sql = "select id,name,email,birth from customers where id < ?";
            // connection 连接,sql :sql语句,ArrayListHandler:存储形式,params 可变参数:填充占位符,可以不传参数,但不要传null
            List<Object[]> list = queryRunner.query(connection, sql, arrayListHandler, 30); // 执行sql语句
            list.forEach(System.out::println);


            // 可以将创建存储形成,和执行sql,一体化 如下:
            List<Object[]> query = queryRunner.query(connection, sql, new ArrayListHandler(), 30);
            query.forEach(System.out::println);

            // 没有查询到的返回null
            List<Object[]> query2 = queryRunner.query(connection, sql, new ArrayListHandler(), -1);
            query.forEach(System.out::println);

        } catch (Exception e) {
            throw new RuntimeException(e);  // 将编译异常转换为运行异常抛出
        }

    }
}

3. BeanHandler

BeanHandler :把 select 查询显示的结果集中的 第一行 数据封装存储到一个对应的 JavaBean(ORM映射类) 的实例对象当中去。简单的说就是处理 “一条”记录

具体代码如下:

import com.alibaba.druid.pool.DruidDataSourceFactory;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;

import javax.sql.DataSource;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;

public class ResultSetHandler {
    public static void main(String[] args) {
        // 读取配置文件方式一:
        InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("druid.properties");  // 默认是读取src
        // 目录下的配置文件
        try {
            // 读取配置文件方式二:
            FileInputStream io = new FileInputStream(new File("src/druid.properties"));

            // 创建 Properties对象用于获取到以读取的配置信息参数
            Properties properties = new Properties();
            properties.load(io);   // 以简单的线性格式读取属性列表(关键字/元素对)
            // 通过传入读取配置文件的对象,创建 druid数据库连接池
            DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
            // 获取到 druid 数据库连接池中的连接
            Connection connection = dataSource.getConnection();


            // 创建存储 select 查询的存储方式:这里是  BeanHandler<> 存储 "一条" 记录,javaBean实例对象存储起来单条记录
            BeanHandler<Customer> beanHandler = new BeanHandler<>(Customer.class);
            // 创建 QueryRunner 对象使用其中的 ResultSetHandler接口中的方法
            QueryRunner queryRunner = new QueryRunner();
            String sql = "select id,name,email,birth from customers where id = ?";
            // connection 连接,sql :sql语句,BeanHandler<>:存储形式,params 可变参数:填充占位符,可以不传参数,但不要传null
            Customer customer = queryRunner.query(connection, sql, beanHandler, 10);
            System.out.println(customer);


            // 可以将创建存储形成,和执行sql,一体化 如下:
            Customer customer1 = queryRunner.query(connection, sql, new BeanHandler<>(Customer.class), 10);
            System.out.println(customer1);


            // 没有查询到的返回null
            Customer customer2 = queryRunner.query(connection, sql, new BeanHandler<>(Customer.class), 100);
            System.out.println(customer2);
        } catch (Exception e) {
            throw new RuntimeException(e);  // 将编译异常转换为运行异常抛出
        }


    }
}

在这里插入图片描述


4. BeanListHandler

BeanListHandler : 把 select 查询显示的结果集中的 所有每一行 数据都先封装存储到一个对应的 JavaBean(ORM映射类) 的实例对象当中去,再将这些 JavaBean实例对象,存放到 List 链表当中

简单的说就是查询处理“多条”记录

具体代码实现如下:

import com.alibaba.druid.pool.DruidDataSourceFactory;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;

import javax.sql.DataSource;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;

public class ResultSetHandler {
    public static void main(String[] args) {
        // 读取配置文件方式一:
        InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("druid.properties");  // 默认是读取src
        // 目录下的配置文件
        try {
            // 读取配置文件方式二:
            FileInputStream io = new FileInputStream(new File("src/druid.properties"));

            // 创建 Properties对象用于获取到以读取的配置信息参数
            Properties properties = new Properties();
            properties.load(io);   // 以简单的线性格式读取属性列表(关键字/元素对)
            // 通过传入读取配置文件的对象,创建 druid数据库连接池
            DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
            // 获取到 druid 数据库连接池中的连接
            Connection connection = dataSource.getConnection();


            // 创建存储 select 查询的存储方式:这里是  BeanListHandler<> 存储 "多条" 记录,javaBean实例存储一行记录,再将多行JavaBean存储到List链表当中
            BeanListHandler<Customer> beanListHandler = new BeanListHandler<>(Customer.class);
            // 创建 QueryRunner 对象使用其中的 ResultSetHandler接口中的方法
            QueryRunner queryRunner = new QueryRunner();
            String sql = "select id,name,email,birth from customers where id < ?";
            // connection 连接,sql :sql语句,beanListHandler:存储形式,params 可变参数:填充占位符,可以不传参数,但不要传null
            List<Customer> customersList = queryRunner.query(connection, sql, beanListHandler, 30);
            customersList.forEach(System.out::println);
            System.out.println("****************************************************************");

            // 可以将创建存储形成,和执行sql,一体化 如下:
            List<Customer> list = queryRunner.query(connection, sql, new BeanListHandler<Customer>(Customer.class), 30);
            for(Customer c : list) {
                System.out.println(c);
            }


            System.out.println("****************************************************************");
            // 没有查询到的返回null
            List<Customer> query = queryRunner.query(connection, sql, new BeanListHandler<Customer>(Customer.class),
                    -1);
            query.forEach(System.out::println);
        } catch (Exception e) {
            throw new RuntimeException(e);  // 将编译异常转换为运行异常抛出
        }


    }
}

在这里插入图片描述


5. MapHandler

MapHandler : 把 select 查询显示的结果集中的 第一行 数据封装存储到一个 Map 里,key 是列名,value就是对应列名的值。简单的说就是处理 “一条”记录

具体代码实现如下:

import com.alibaba.druid.pool.DruidDataSourceFactory;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.*;

import javax.sql.DataSource;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Properties;

public class ResultSetHandler {
    public static void main(String[] args) {
        // 读取配置文件方式一:
        InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("druid.properties");  // 默认是读取src
        // 目录下的配置文件
        try {
            // 读取配置文件方式二:
            FileInputStream io = new FileInputStream(new File("src/druid.properties"));

            // 创建 Properties对象用于获取到以读取的配置信息参数
            Properties properties = new Properties();
            properties.load(io);   // 以简单的线性格式读取属性列表(关键字/元素对)
            // 通过传入读取配置文件的对象,创建 druid数据库连接池
            DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
            // 获取到 druid 数据库连接池中的连接
            Connection connection = dataSource.getConnection();


            // 创建存储 select 查询的存储方式:这里是  MapHandler 存储 "一条" 记录,以键值对的方式存储一条记录
            MapHandler mapHandler = new MapHandler();
            // 创建 QueryRunner 对象使用其中的 ResultSetHandler接口中的方法
            QueryRunner queryRunner = new QueryRunner();

            // connection 连接,sql :sql语句,MapHandler:存储形式,params 可变参数:填充占位符,可以不传参数,但不要传null
            String sql = "select id,name,email,birth from customers where id = ?";
            Map<String, Object> map = queryRunner.query(connection, sql, mapHandler, 10);
            System.out.println(map);

            // 可以将创建存储形成,和执行sql,一体化 如下:
            Map<String, Object> map2 = queryRunner.query(connection, sql, new MapHandler(), 10);
            System.out.println(map2);

            // 没有查询到的返回null
            Map<String, Object> map3 = queryRunner.query(connection, sql, new MapHandler(), 0);
            System.out.println(map3);
        } catch (Exception e) {
            throw new RuntimeException(e);  // 将编译异常转换为运行异常抛出
        }


    }
}

在这里插入图片描述


6. MapListHandler

MapListHandler :把 select 查询显示的结果集中的 所有每一行 数据先封装存储到一个Map 里,然后再存放到 LIst 链表当中去。简单的说就是“处理多条记录”

具体代码实现如下:

import com.alibaba.druid.pool.DruidDataSourceFactory;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.*;

import javax.sql.DataSource;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Properties;

public class ResultSetHandler {
    public static void main(String[] args) {
        // 读取配置文件方式一:
        InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("druid.properties");  // 默认是读取src
        // 目录下的配置文件
        try {
            // 读取配置文件方式二:
            FileInputStream io = new FileInputStream(new File("src/druid.properties"));

            // 创建 Properties对象用于获取到以读取的配置信息参数
            Properties properties = new Properties();
            properties.load(io);   // 以简单的线性格式读取属性列表(关键字/元素对)
            // 通过传入读取配置文件的对象,创建 druid数据库连接池
            DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
            // 获取到 druid 数据库连接池中的连接
            Connection connection = dataSource.getConnection();


            // 创建存储 select 查询的存储方式:这里是  MapListHandler 存储 "多条" 记录,以键值对的形式存储起来单条记录,再将单条记录全部存储到List链表中
            MapListHandler mapListHandler = new MapListHandler();
            // 创建 QueryRunner 对象使用其中的 ResultSetHandler接口中的方法
            QueryRunner queryRunner = new QueryRunner();
            // connection 连接,sql :sql语句,MapListHandler:存储形式,params 可变参数:填充占位符,可以不传参数,但不要传null
            String sql = "select id,name,email,birth from customers where id < ?";
            List<Map<String, Object>> mapList = queryRunner.query(connection, sql, mapListHandler, 30);
            mapList.forEach(System.out::println);


            System.out.println("****************************************************************");
            // 可以将创建存储形成,和执行sql,一体化 如下:
            List<Map<String, Object>> mapList2 = queryRunner.query(connection, sql, new MapListHandler(), 30);
            for(Map m : mapList2) {
                System.out.println(m);
            }


            System.out.println("****************************************************************");
            // 没有查询到的返回null
            List<Map<String, Object>> mapList3 = queryRunner.query(connection, sql, mapListHandler, 0);
            mapList3.forEach(System.out::println);
        } catch (Exception e) {
            throw new RuntimeException(e);  // 将编译异常转换为运行异常抛出
        }

    }
}

在这里插入图片描述


7. ColumnListHandler

ColumnListHandler : select 查询显示的结果集中的 某一列 数据存放到 List 链表当中

注意:某一列 可以是下标new ColumnListHandler(1) 也可以是列名(别名)new ColumnListHandler("name"),需要注意的是如果是下标的话,起始下标是 从 1 开始的,不是从 0 开始的。

具体代码实现如下:

import com.alibaba.druid.pool.DruidDataSourceFactory;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.*;

import javax.sql.DataSource;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Properties;

public class ResultSetHandler {
    public static void main(String[] args) {
        // 读取配置文件方式一:
        InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("druid.properties");  // 默认是读取src
        // 目录下的配置文件
        try {
            // 读取配置文件方式二:
            FileInputStream io = new FileInputStream(new File("src/druid.properties"));

            // 创建 Properties对象用于获取到以读取的配置信息参数
            Properties properties = new Properties();
            properties.load(io);   // 以简单的线性格式读取属性列表(关键字/元素对)
            // 通过传入读取配置文件的对象,创建 druid数据库连接池
            DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
            // 获取到 druid 数据库连接池中的连接
            Connection connection = dataSource.getConnection();

            // 创建存储 select 查询的存储方式:这里是  ColumnListHandler 存储 "某一列中所有的" 记录,以List链表的形式存储起来单条记录
            ColumnListHandler columnListHandler = new ColumnListHandler(1);  // 注意的是 在jdbc 中起始下标是从 1开始的不是从 0 开始的
            // 创建 QueryRunner 对象使用其中的 ResultSetHandler接口中的方法
            QueryRunner queryRunner = new QueryRunner();

            String sql = "select id,name,email,birth from customers where id < ?";
            // connection 连接,sql :sql语句,columnListHandler:存储形式,params 可变参数:填充占位符,可以不传参数,但不要传null
            List<Object> list = queryRunner.query(connection, sql, columnListHandler, 30);
            list.forEach(System.out::println);


            System.out.println("****************************************************************");
            // 可以将创建存储形成,和执行sql,一体化 如下:
            List<Object> list2 = queryRunner.query(connection, sql, new ColumnListHandler("name"), 30);  // 可以是列名(别名)
            for(Object o : list2) {
                System.out.println(o);
            }


            System.out.println("****************************************************************");
            // 没有查询到的返回null
            List<Object> list3 = queryRunner.query(connection, sql, new ColumnListHandler(1), 0);
            list3.forEach(System.out::println);
        } catch (Exception e) {
            throw new RuntimeException(e);  // 将编译异常转换为运行异常抛出
        }


    }
}

在这里插入图片描述


8. ScalarHandler

ScalarHandler :查询单个特殊值的对象。如:count(), max(),sum()

需要注意的是:最后返回的结果,要进行一个强制转换为你,所想要对应的数据类型

具体代码是实现如下:

import com.alibaba.druid.pool.DruidDataSourceFactory;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.*;

import javax.sql.DataSource;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Properties;

public class ResultSetHandler {
    public static void main(String[] args) {
        // 读取配置文件方式一:
        InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("druid.properties");  // 默认是读取src
        // 目录下的配置文件
        try {
            // 读取配置文件方式二:
            FileInputStream io = new FileInputStream(new File("src/druid.properties"));

            // 创建 Properties对象用于获取到以读取的配置信息参数
            Properties properties = new Properties();
            properties.load(io);   // 以简单的线性格式读取属性列表(关键字/元素对)
            // 通过传入读取配置文件的对象,创建 druid数据库连接池
            DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
            // 获取到 druid 数据库连接池中的连接
            Connection connection = dataSource.getConnection();


            // 创建存储 select 查询的存储方式:这里是  ScalarHandler 处理特殊的查询结果 比如: max(),sum(),count()
            ScalarHandler scalarHandler = new ScalarHandler();
            // 创建 QueryRunner 对象使用其中的 ResultSetHandler接口中的方法
            QueryRunner queryRunner = new QueryRunner();
            String sql = "select count(*) from customers";
            // connection 连接,sql :sql语句,columnListHandler:存储形式,params 可变参数:填充占位符,可以不传参数,但不要传null
            long count = (long)queryRunner.query(connection,sql,scalarHandler);    // 强制转换为你所需要的对应的数据类型
            System.out.println("count: "+count);

            // 可以将创建存储形成,和执行sql,一体化 如下:
            String sql2 = "select max(id) from customers";
            int max = (int)queryRunner.query(connection,sql2,new ScalarHandler());  // 强制转换为你所需要的对应的数据类型
            System.out.println("max: "+max);
        } catch (Exception e) {
            throw new RuntimeException(e);  // 将编译异常转换为运行异常抛出
        }


    }
}

在这里插入图片描述


4. DbUtils

DbUtils :提供如关闭连接、装载JDBC驱动程序等常规工作的工具类,里面的所有方法都是静态的。主要方法如下:

  • public static void close(…) throws java.sql.SQLException: DbUtils类提供了三个重载的关闭方法。这些方法检查所提供的参数是不是NULL,如果不是的话,它们就关闭Connection、Statement和ResultSet。
  • public static void closeQuietly(…): 这一类方法不仅能在Connection、Statement和ResultSet为NULL情况下避免关闭,还能隐藏一些在程序中抛出的SQLEeception。
  • public static void commitAndClose(Connection conn)throws SQLException: 用来提交连接的事务,然后关闭连接
  • public static void commitAndCloseQuietly(Connection conn): 用来提交连接,然后关闭连接,并且在关闭连接时不抛出SQL异常。
  • public static void rollback(Connection conn)throws SQLException:允许conn为null,因为方法内部做了判断
  • public static void rollbackAndClose(Connection conn)throws SQLException
  • rollbackAndCloseQuietly(Connection)
  • public static boolean loadDriver(java.lang.String driverClassName):这一方装载并注册JDBC驱动程序,如果成功就返回true。使用该方法,你不需要捕捉这个异常ClassNotFoundException。
  • index.html 中也有相关的帮助文档如下:

在这里插入图片描述

需要注意的一点就是:如果是使用数据库连接池获取其中的连接,是归还连接不是关闭连接,而如果是直接使用 传统的JDBC 连接的话是 关闭连接 归还连接,释放资源 最晚使用的资源最先关闭,

使用 DbUtils.jar 中提供的 DbUtils 工具类,实现资源的关闭:

方式一: 使用public static void close(…) throws java.sql.SQLException 关闭资源/归还连接,需要你手动处理异常

下面是对其方法的一个封装

具体代码实现如下:

package Blogs.blogs04;

import org.apache.commons.dbutils.DbUtils;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class Close {
    public static void closeResource(Connection connection, Statement statement, ResultSet resultSet) {
        // 归还连接,释放资源 最晚使用的资源最先关闭,
        try {
            DbUtils.close(resultSet);  // 静态方法可以“类名.方法名”直接调用// 释放处理查询结果集的资源
        } catch (SQLException e) {
            throw new RuntimeException(e);  // 将编译异常转换为运行异常抛出
        }

        try {
            DbUtils.close(statement);       // 释放操作数据库的资源
        } catch (SQLException e) {
            throw new RuntimeException(e);  // 将编译异常转换为运行异常抛出
        }

        try {
            DbUtils.close(connection);      // 关闭连接/归还连接(数据库连接池)
        } catch (SQLException e) {
            throw new RuntimeException(e);  // 将编译异常转换为运行异常抛出
        }
    }
}

方式二: 使用public static void closeQuietly(…) 关闭资源,不用处理异常,它的方法中自动帮你处理了异常。

具体代码实现如下:

import org.apache.commons.dbutils.DbUtils;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class Close {
    public static void close(Connection connection,Statement statement,ResultSet resultSet) {
        // 归还连接,释放资源 最晚使用的资源最先关闭,
        // 静态方法可以“类名.方法名”直接调用
        DbUtils.closeQuietly(resultSet);   // 释放处理查询结果集的资源
        DbUtils.closeQuietly(statement);   // 释放操作数据库的资源
        DbUtils.closeQuietly(connection);  // 关闭连接/归还连接(数据库连接池)
    }
}

5. 结合使用 Druid(德鲁伊)数据库连接池 以及 Apache-DBUtils 进行一个 DAO 封装实例演示

DAO: Data Access Object访问数据信息的类和接口,包括了对数据的CRUD(Create、Retrival、Update、Delete),而不包含任何业务相关的信息。有时也称作:BaseDAO

作用:为了实现功能的模块化,更有利于代码的维护和升级。

下面是对 actor 数据表,结合使用 Apache-DBUtils中的 QueryRunner,ResultSetHandler以及Druid 数据库连接池,最后的DbUtils(释放资源)

在这里插入图片描述

在这里插入图片描述

进行一个 DAO的封装,执行 DDL(增,删,改)以及 DQL(查询)操作。

具体方法的框架图如下:

在这里插入图片描述


Actor javaBean

**public class Actor ** JavaBean 实例,ORM数据表的映射

package day05.ActorDAOExample;

import java.sql.Date;

public class Actor {
    private int id;
    private String name;
    private String sex;
    private Date birth;
    private String phone;

    public Actor() {
        // 必须定义一个无参的构造器,用于反射获取对应的属性值,进行一个赋值操作
    }


    public Actor(int id, String name, String sex, Date birth, String phone) {
        this.id = id;
        this.name = name;
        this.sex = sex;
        this.birth = birth;
        this.phone = phone;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getId() {
        return id;
    }


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public Date getBirth() {
        return birth;
    }

    public void setBirth(Date birth) {
        this.birth = birth;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }


    @Override
    public String toString() {
        return "Actor{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                ", birth=" + birth +
                ", phone='" + phone + '\'' +
                '}';
    }
}

BasicDAO<T>

**public abstract class BasicDAO<T> ** 通用数据表的 Druid(德鲁伊)数据库连接池,获取连接,使用使用 Apache-DBUtils中的 QueryRunner,ResultSetHandler,DbUtils(释放资源) 操作数据表 DDL(增删改) ,DQL(查询)

package day05.ActorDAOExample;

import com.alibaba.druid.pool.DruidDataSourceFactory;
import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.*;

import javax.sql.DataSource;
import java.io.File;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
import java.util.Map;
import java.util.Properties;

public abstract class BasicDAO<T> {  // 定义抽象类,抽象类不可以new

    /**
     * 处理查询单个特殊的查询操作 max() count()
     *  使用 dbutils封装的工具类,操作数据库,以及执行sql语句,处理select查询的结果集
     *  ScalarHandler:查询单个值对象
     * @param sql
     * @param args
     * @return Object
     */
    public Object getScalarHandler(String sql,Object...args) {
        // 1. 注册驱动,2.连接数据库,这里通过使用 dbutils 数据库连接池获取到其中的一个连接对象
        Connection connection = getDruidConnection();

        // 2.创建dbutils封装的工具类对象,调用其中封装的方法操作数据库,执行sql语句,处理select结果集
        QueryRunner queryRunner = new QueryRunner();

        // 创建存储select 查询结果集的对象这里是 : ScalarHandler 单个值对象
        ScalarHandler scalarHandler = new ScalarHandler();

        // 执行sql语句,以及处理select 查询的结果集对象
        Object object = null;
        try {
            object = queryRunner.query(connection, sql, scalarHandler, args);
            return object;
        } catch (SQLException e) {
            throw new RuntimeException(e);  // 将编译异常转换为运行异常抛出.
        } finally {
            // 关闭资源,最晚使用的最先关闭,如果使用数据库连接池,则是 “归还连接”,不是关闭连接
            close(null,null,connection);
        }

        // 或者将创建select 查询的结果集对象和执行sql语句以及处理select查询的结果封装为一体
//        Object o = queryRunner.query(connection, sql, new ScalarHandler(), args);

    }






    /**
     * 查询所有记录
     * 使用dbutils 封装的工具类,执行sql语句操作数据库,
     * MapListHandler:将select查询的结果集中的"所有"每一行数据都封装到一个Map里,然后再存放到List
     * @param sql
     * @param args
     * @return List<Map<String,Object>>
     */
    public List<Map<String,Object>> getMapListHandler(String sql,Object...args) {
        // 1. 注册驱动,连接数据库,使用从 druid数据库连接池中获取到的其中的一个连接对象
        Connection connection = getDruidConnection();

        // 2. 创建dbutils 封装的工具类对象,用于调用其中的方法操作数据库以及处理select 查询的结果集
        QueryRunner queryRunner = new QueryRunner();

        // 创建存储select 查询的结果集对象,这里我们使用的是: MapListHandler
        MapListHandler mapListHandler = new MapListHandler();
        // 执行sql语句,并处理select 查询的结果集数据
        List<Map<String,Object>> list = null;
        try {
            list = queryRunner.query(connection, sql, mapListHandler, args);
            return list;
        } catch (SQLException e) {
            throw new RuntimeException(e);   // 将编译异常转换为运行异常抛出
        }

        // 或者将创建select查询结果集的对象,以及执行sql语句,处理结果集一体化
        // List<Map<String, Object>> mapList = queryRunner.query(connection, sql, new MapListHandler(),args);
    }



    /**
     * 查询一条记录
     * 使用 dbutils 封装的工具类进行操作数据库以及处理select 查询的结果集
     * MapHandler:将结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值。
     * @param sql
     * @param args
     * @return  Map<String,Object>
     */
    public Map<String,Object> getMapHandler(String sql, Object...args) {
        // 1. 注册驱动,连接数据库,这里使用从 druid数据库连接池中获取其中的一个连接对象
        Connection connection = getDruidConnection();

        // 创建Dbutils 封装的工具类的对象,用于调用其中的方法,操作数据库和处理select 查询的结果集
        QueryRunner queryRunner = new QueryRunner();

        // 创建存储select 查询结果集的集合对象,这里我们使用 MapHandler 对象
        MapHandler mapHandler = new MapHandler();
        try {
            // 执行sql语句,处理select的结果集
            Map<String,Object> map = queryRunner.query(connection,sql,mapHandler,args);// 可变参数可以不传参数,不要传null

            // 或者将创建存储select 查询的结果集,和执行sql语句,处理select查询的结果集一体化
            // Map<String, Object> map = queryRunner.query(connection, sql, new MapHandler(), args);
            return map;
        } catch (SQLException e) {
            throw new RuntimeException(e);   // 将编译异常转换为运行异常抛出
        } finally {
            // 6.关闭资源(最晚使用的最先关闭),如果使用的数据库连接池,则是“归还连接” 不是关闭连接
            close(null,null,connection);
        }

    }



    /**
     *  使用 Dbutils封装的工具类,处理 "多条" 记录
     *  ArrayListHandler:把 select查询的 结果集中的每一行数据都转成一个数组,再存放到List集合链表当中
     * @param sql
     * @param clazz
     * @param args
     * @return List<Object[]>
     */
    public List<Object[]> getArrayListHandler(String sql, Class<T> clazz, Object...args) {
        // 1. 注册驱动,2. 连接数据库,这里通过从 druid  数据库连接池中获取到其中的一个连接对象
        Connection connection = getDruidConnection();

        // 2. 创建Dbutils封装的工具类的对象,用于调用其中的方法操作数据库以及处理select 查询的结果集
        QueryRunner queryRunner = new QueryRunner();

        // 3. 创建存储select 查询结果集的集合对象,这里我们使用: ArrayListHandler
        ArrayListHandler arrayListHandler = new ArrayListHandler();
        // 执行sql语句,并处理select 查询的结果集

        try {
            List<Object[]> list= queryRunner.query(connection, sql, arrayListHandler, args);

            // 或者将创建存储select 查询结果集的对象,和 执行sql语句以及处理select 查询的结果集一体化
            // List<Object[]> query = queryRunner.query(connection, sql, new ArrayListHandler(), args); //
            // 可变参数可以不传参数,但是不要传null(防止null引用,报错)

            return list;
        } catch (SQLException e) {
            throw new RuntimeException(e);   // 将编译异常转换为运行异常抛出
        } finally {
            // 关闭了资源,最晚使用的最先关闭,如果使用数据库连接池,则是“归还连接” 不是关闭连接
            close(null,null,connection);
        }

    }


    /**
     * 使用 Dbutils 封装的工具类,处理 “一条” 记录
     * ArrayHandler:把select 查询到的结果集中的第一行数据转成对象数组。存储起来
     * @param sql
     * @param clazz
     * @param args
     * @return Object[]
     */
    public Object[] getArrayHandler(String sql,Class<T> clazz,Object...args) {
        // 1. 注册驱动,2.获取连接,通过dbutils 数据库连接池中获取到其中的一个连接对象
        Connection connection = getDruidConnection();


        // 3. 执行sql语句,并处理select 查询的结果集
        QueryRunner queryRunner = new QueryRunner();   // 创建dbutils工具类的对象,用于调用其中的封装的方法

        // 2. 创建存储select 查询的结果集的对象,这里我们使用的是: ArrayHandler “以数组的形式存储一条记录”
/*        ArrayHandler arrayHandler = new ArrayHandler();
        Object[] arr = queryRunner.query(connection, sql, arrayHandler, args);*/

        Object[] arr = {};
        try {
            // 也可以将创建select 查询结果集的存储对象,和执行 QueryRunner.query()结合在一起
             arr = queryRunner.query(connection, sql, new ArrayHandler(), args);
        } catch (SQLException e) {
            throw new RuntimeException(e);   // 将编译异常转换为运行异常抛出
        } finally {
            // 关闭资源,(最晚使用的最先关闭),如果是数据库连接池,则是 “归还连接” ,不是关闭连接
            close(null,null,connection);
        }
        return arr;

    }

    /**
     * 使用 dbutils 工具类封装处理 “多条” 记录
     * BeanListHandler:将select查询的结果集所有的每一行数据都封装到一个对应的JavaBean(ORM映射)实例中,存放到List里。
     * @param sql
     * @param clazz
     * @param args
     * @return List<T>
     */
    public List<T> getBeanListHandler(String sql, Class<T> clazz, Object...args) {
        // 1. 注册驱动,2.获取连接,通过 dbutils 数据库连接池获取其中的一个连接对象
        Connection connection = getDruidConnection();



        QueryRunner queryRunner = new QueryRunner();   // 创建dbutils工具类对象,用于使用其中的封装的的方法

        List<T> list = null;   // ResultSetHandler接口中的BeanListHandler返回类型.
        try {
            // 3. 执行sql语句,并处理select 查询的结果集,
            // 2. 创建存储select 查询的结果集的对象,这里我们使用: BeanListHandler
            BeanListHandler<T> beanListHandler = new BeanListHandler<T>(clazz);  // 泛型
            // ResultSetHandler接口中的BeanListHandler返回查询select查询到的结果集的 javaBean实例对象,存放到list集合中
            list = queryRunner.query(connection, sql, beanListHandler, args);

            // 或者将创建select 存储对象和执行sql语句一体化
//            list = queryRunner.query(connection, sql, new BeanListHandler<T>(clazz), args);

        } catch (SQLException e) {
            throw new RuntimeException(e);  // 将编译异常转换为运行异常抛出
        } finally {
            // 关闭资源(最晚使用的最先关闭),如果是从数据库连接池中获取到连接对象则是 “归还连接”,不是关闭连接
            close(null,null,connection);
        }
        return list;

    }


    /**
     * 使用 dubitls 封装的工具类进行查询处理操作 ,“处理一条” 记录
     * BeanHandler:将select查询到的结果集中的第一行数据封装到一个对应的JavaBean(orm映射类中)实例中。存储起来
     * @param sql
     * @param clazz
     * @param args
     * @return T 一条记录
     */
    public T getBeanHandler(String sql ,Class<T> clazz,Object...args) {
        // 获取到 driod 数据库连接池的其中一个连接对象
        Connection connection = getDruidConnection();

        // 创建Dbutils 封装工具类的对象,使用其中的封装的方法
        QueryRunner queryRunner = new QueryRunner();


        // 执行sql语句,并处理select 查询的结果集
        T t = null;  // 创建queryRunner 处理结果集的返回类型

        // 执行sql语句,返回类型
        try {
            // 创建存放 select 结果集中实例对象,使用泛型,这里我们使用  BeanHandler<T> 类型 "将查询的一行记录存储到javaBean orm 实例对象中"
            BeanHandler<T> beanHandler = new BeanHandler<>(clazz);
            t = queryRunner.query(connection, sql, beanHandler, args);


            // 或者创建存储对象和执行sql语句一体化
//            t = queryRunner.query(connection, sql, new BeanHandler<>(clazz), args);

        } catch (SQLException e) {
            throw new RuntimeException(e);  // 将编译异常转换为运行异常抛出
        } finally {
            // 6.关闭资源连接,最晚使用的最先释放,使用的数据库连接池,则就是“归还连接”
            close(null,null,connection);
        }
        return t;

    }


    /**
     * 使用 dbutils工具类,封装通用数据表的增删改
     * @param sql sql语句
     * @param args args 填充的占位符
     * @return int 返回影响数据库的记录
     */
    public int update(String sql, Object...args) {
        // 通过自行封装的 Druid数据库连接池中获取连接对象
        Connection connection = getDruidConnection();
        // 通过 dbutils 工具类创建数据库操作对象
        QueryRunner queryRunner =  new QueryRunner();
        int updateCount = 0;   // 影响数据库的行数
        try {
            updateCount = queryRunner.update(connection,sql,args);  // 返回影响数据库的行数记录
        } catch (SQLException e) {
            throw new RuntimeException(e);  // 将编译异常转换为运行异常抛出
        } finally {
            //  关闭资源,使用了数据库连接池就是 “归还连接”不是关闭连接
            close(null,null,connection);
        }
        return updateCount;
    }





    private static DataSource dataSource = null;     // druid 数据库连接池的对象,同样以类属性的形式存在,
    // 注意静态的static 不用使用 this引用,类中不可以调用方法(方法的调用是在“代码块中,静态代码块,方法代码块”)
    static {  // static 静态代码块,和类一起加载到堆区当中,仅仅只是执行一次,所有对象共用,符合一个数据库连接池的构想

        Properties properties = new Properties();   // 创建获取.properties后缀的配置文件的信息的对象
        try {
            FileInputStream is = new FileInputStream(new File("src/druid.properties")); // 获取到指定路径下的配置文件的信息
            properties.load(is);  // 以简单的线性格式输入字符获取到属性列表(关键字/元素对)

            // 传入获取配置文件的信息的对象,创建druid 数据库连接池
            dataSource = DruidDataSourceFactory.createDataSource(properties);  // 注意返回类型是 DataSource jdbc 接口的实现类
        } catch (Exception e) {
            throw new RuntimeException(e);  // 将编译异常转换为运行异常抛出。
        }

    }

    /**
     * 通过 druid 数据库连接池获取到连接对象
     * 注意我们只需要一个数据库连接池,当连接不够时,通过增加数据库连接池中的连接数量.不要创建多个数据库连接池
     * @return Connection
     */
    private static Connection getDruidConnection() {
        Connection connection = null;
        // 从druid 数据库连接池获取到其中的一个连接对象
        try {
            connection = dataSource.getConnection();
        } catch (SQLException e) {
            throw new RuntimeException(e);  // 将编译异常转换为运行时异常抛出。
        }
        return connection;   // 返回从数据库连接池中获取到的对象
    }




    /**
     * 使用 DButils 工具类关闭资源(最晚使用的最先关闭),
     * 如果是从数据库连接池中获取到的连接,则是“归还连接” 并不是关闭连接
     * @param resultSet
     * @param statement
     * @param connection
     */
    private static void close(ResultSet resultSet, Statement statement, Connection connection) {
        // 方式一;需要处理异常,
        /*try {
            DbUtils.close(resultSet);
        } catch (SQLException e) {
            throw new RuntimeException(e);  // 将编译异常转换为运行异常抛出
        }

        try {
            DbUtils.close(statement);
        } catch (SQLException e) {
            throw new RuntimeException(e);  // 将编译异常转换为运行异常抛出
        }

        try {
            DbUtils.close(resultSet);
        } catch (SQLException e) {
            throw new RuntimeException(e);  // 将编译异常转换为运行异常抛出
        }*/

        // 方式二: 不用处理异常,它自动处理了异常

        DbUtils.closeQuietly(resultSet);
        DbUtils.closeQuietly(statement);
        DbUtils.closeQuietly(connection);

    }

}

ActorDAO

**public interface ActorDAO **关Actor数据表的 “增,删,改,查”操作的接口的封装

package day05.ActorDAOExample;


import java.sql.Date;
import java.util.List;
import java.util.Map;

/**
 * 有关Actor数据表的 “增,删,改,查”操作的接口的封装
 */
public interface ActorDAO {  // interface 接口是不可以new的

    /**
     * 对数据表 actor 数据表的增删改
     * @param sql
     * @param args
     * @return int 返回影响数据库的行数
     */
    public int updateActor(String sql,Object...args);


    /**
     *  求数据表 actor 中最大的 birth
     * @param sql
     * @param args
     * @return Date 返回 actor 数据表中最大 birth
     */
    public Date maxBirth(String sql, Object...args);


    /**
     * 求数据表中的含有的记录条数
     * @param sql
     * @param args
     * @return long
     */
    public long countActor(String sql, Object...args);

    /**
     * 使用 ResultSetHandler接口中的BeanHandler 处理查询 “一条”记录
     * @param sql
     * @param args
     * @return Actor
     */
    public Actor getBeanHandler(String sql ,Object...args);


    /**
     * 使用ResultSetHandler接口中的BeanListHandler 处理查询 “多条记录”
     * @param sql
     * @param args
     * @return List
     */
    public List getBeanListHandler(String sql, Object...args);


    /**
     * 使用ResultSetHandler接口中的ArrayHandler 处理“一条”记录
     * @param sql
     * @param args
     * @return Object[]
     */
    public Object[] getArrayHandler(String sql,Object...args);


    /**
     * 使用ResultSetHandler接口中的ArrayListHandler 处理"多条" 记录
     * @param sql
     * @param args
     * @return List
     */
    public  List getArrayListHandler(String sql,Object...args);


    /**
     * 使用ResultSetHandler 接口中的Map<String,Actor>  处理“一条记录”
     * @param sql
     * @param args
     * @return Map<String,Object>
     */
    public Map<String, Object> getMapHandlers(String sql, Object...args);


    /**
     * 使用ResultSetHandler 接口中的MapListHandler 处理 “多条记录”
     * @param sql
     * @param args
     * @return List
     */
    public List getMapListHandlers(String sql,Object...args);


}

Actorlmp

public class Actorlmp extends BasicDAO<Actor> implements ActorDAO 通过继承父类BasicDAO<Actor> 调用父类中的方法,实现对 ActorDAO接口中的抽象方法。

package day05.ActorDAOExample;

import java.sql.Date;
import java.util.List;
import java.util.Map;

public class Actorlmp extends BasicDAO<Actor> implements ActorDAO{

    /**
     * 对数据表 actor 数据表的增删改
     * @param sql
     * @param args
     * @return int 返回影响数据的行数
     */
    @Override
    public int updateActor(String sql, Object... args) {
        return super.update(sql,args);
    }

    /**
     * 求数据表 actor 中最大的 birth
     * @param sql
     * @param args
     * @return Date 最大的出生日期
     */
    @Override
    public Date maxBirth(String sql, Object... args) {
        return (Date)super.getScalarHandler(sql,args);
    }


    /**
     * 求数据表中的含有的记录条数
     * @param sql
     * @param args
     * @return long
     */
    @Override
    public long countActor(String sql, Object... args) {
        return (long)super.getScalarHandler(sql,args);
    }

    /**
     * 使用 ResultSetHandler接口中的BeanHandler 处理查询 “一条”记录
     * @param sql
     * @param args
     * @return Actor
     */
    @Override
    public Actor getBeanHandler(String sql, Object... args) {
        return super.getBeanHandler(sql,Actor.class,args);
    }


    /**
     *使用ResultSetHandler接口中的BeanListHandler 处理查询 “多条记录”
     * @param sql
     * @param args
     * @return List
     */
    @Override
    public List getBeanListHandler(String sql, Object... args) {
        return super.getBeanListHandler(sql,Actor.class,args);
    }

    /**
     * 使用ResultSetHandler接口中的ArrayHandler 处理“一条”记录
     * @param sql
     * @param args
     * @return Object[]
     */
    @Override
    public Object[] getArrayHandler(String sql, Object... args) {
        return super.getArrayHandler(sql,Actor.class,args);
    }

    /**
     * 使用ResultSetHandler接口中的ArrayListHandler 处理"多条" 记录
     * @param sql
     * @param args
     * @return  List
     */
    @Override
    public List getArrayListHandler(String sql, Object... args) {
        return (List)super.getArrayListHandler(sql,Actor.class,args);
    }

    /**
     * 使用ResultSetHandler 接口中的Map<String,Actor>  处理“一条记录”
     * @param sql
     * @param args
     * @return Map<String, Object>
     */
    @Override
    public Map<String, Object> getMapHandlers(String sql, Object... args) {
        return super.getMapHandler(sql,args);
    }


    /**
     * 使用ResultSetHandler 接口中的MapListHandler 处理 “多条记录”
     * @param sql
     * @param args
     * @return List
     */
    @Override
    public List getMapListHandlers(String sql, Object... args) {
        return super.getMapListHandler(sql,args);
    }
}


ActorlmpTest

ActorlmpTest 测试所有的编写结构是否有Bug

package day05.ActorDAOExample;

import com.sun.xml.internal.bind.v2.runtime.RuntimeUtil;

import java.sql.Array;
import java.sql.Date;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

public class ActorlmpTest {
    private static Actorlmp actorlmp = new Actorlmp();    // 创建Actorlmp 对象作为类的属性存在
    public static void main(String[] args) {
        // insert 插入数据
        String sql = "insert into actor(name,sex,birth,phone) values(?,?,?,?)"; // 占位符不要加单引号不然就成了字符串了,失去了占位符的作用了
        // System.out.println(actorlmp.updateActor(sql,"小红","女","2020-10-1","985"));

        // update 修改数据
        String sql2 = "update actor set phone = ? where id = ? ";
       // System.out.println(actorlmp.updateActor(sql2,"211",2));

        // delect 删除数据
        String sql3 = "delete from actor where id = ?";   // 占位符不要加单引号
      //  System.out.println(actorlmp.updateActor(sql3,5));


        String sql4 = "select max(birth) from actor";
        Date date = actorlmp.maxBirth(sql4);
       // System.out.println(date);

        // 测试特殊查询
        String sql5 = "select count(*) from actor";
      //  System.out.println(actorlmp.countActor(sql5));   // 可变参数是可以不传参数的,但是不要传null,防止null引用报错


        // 测试getArrayHandler 一条记录的查询:
        String sql6 = "select id,name,sex,birth,phone from actor where id = ?";
        Object[] actor= actorlmp.getArrayHandler(sql6, 3);
        // System.out.println(Arrays.toString(actor));

        // 测试 getArrayListHandler 查询多条记录
        String sql7 = "select id,name,birth,phone from actor where id < ?";
        List arrayListHandler = actorlmp.getArrayListHandler(sql7, 5);
        arrayListHandler.forEach(System.out::println);


        // 测试 getBeanHandler 查询一条记录
        Actor beanHandler = actorlmp.getBeanHandler(sql6, 3);
        // System.out.println(beanHandler);

        // 测试 getBeanListHandler 查询多条记录
        List beanListHandler = actorlmp.getBeanListHandler(sql7, 5);
        // beanListHandler.forEach(System.out::println);

        // 测试 getMapHandlers 查询一条记录
        Map<String, Object> mapHandlers = actorlmp.getMapHandlers(sql6, 3);
        // System.out.println(mapHandlers);


        // getMapListHandlers 查询多条记录
        List mapListHandlers = actorlmp.getMapListHandlers(sql7, 5);
        // mapListHandlers.forEach(System.out::println);



    }
}


6. 总结:

  1. 如下是关于 Apache-DBUtilsindex.html 帮助文档相关方法的所在位置

在这里插入图片描述

在这里插入图片描述

  1. 对于 ResultSetHandler 接口中的方法中 select 查询到的结果集的数据的存储 形式有两种 传参方式如下:
 // 可以将创建存储形成,和执行sql,一体化 如下:
            Customer customer = queryRunner.query(connection, sql, new BeanHandler<>(Customer.class), 10);

// 方式二: 单独分开定义创建:
BeanHandler<Customer> beanHandler = new BeanHandler<>(Customer.class);
Customer customer = queryRunner.query(connection, sql, beanHandler, 10);
  1. 关于方法中的可变参数params 可以不传参数,但是不要传 null,存在null引用的报错的

  2. 对于 ResultSetHandler 接口中的方法中 处理 select 查询的结果集,如果对应的数据表中查询不到的结果返回 null

  3. 注意:ColumnListHandler : select 查询显示的结果集中的 某一列 数据存放到 List 链表当中,其中的 某一列 传的可以是列名/别名,也可以是对应列中的下标位置,但是注意其下标位置是从 1 开始的,并不是从 0 开始的,基本上关于 JDBC 的下标位置的访问的起始位置都是从 1 开始的。这点需要大家注意。如下:

ColumnListHandler columnListHandler = new ColumnListHandler(1);
List<Object> list = queryRunner.query(connection, sql, new ColumnListHandler("name"), 30);
  1. ScalarHandler :查询单个特殊值的对象。如:count(), max(),sum(),最后的返回结果默认是 Object 的,所以需要大家手动强制转换为 对应需要的数据类型。

7. 最后:

限于自身水平,其中存在的错误,希望大家给予指教,韩信点兵——多多益善,谢谢大家,后会有期,江湖再见。!!!最后,朋友请留下你来过的证明,谢谢。

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值