06 DBUtils

DBUtils

标签(空格分隔): jdbc


DBUtils简介

DBUtils是什么

DButils:由Apache公司提供,一个对JDBC进行简单封装的开源工具类库,简化dao层的操作。

作用:帮助java程序员,开发Dao层代码的简单框架。

框架的作用:帮助程序员,提高程序的开发效率。

为什么需要DBUtils

在使用Dbutils 之前,我们在Dao层使用的技术是JDBC,那么分析一下JDBC的弊端:

  1. 数据库链接对象、sql语句操作对象,封装结果集对象,这三大对象会重复定义
  2. 封装数据的代码重复,而且操作复杂,代码量大
  3. 释放资源的代码重复

因此我们使用已经封装好的工具类库进行操作,能够减少重复劳动。

DBUtils三个核心类

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 commitAndCloseQuietly(Connection conn): 用来提交连接,然后关闭连接,并且在关闭连接时不抛出SQL异常。

  • public static boolean loadDriver(java.lang.String driverClassName):这一方装载并注册JDBC驱动程序,如果成功就返回true。使用该方法,你不需要捕捉这个异常ClassNotFoundException。

QueryRunner类

该类简单化了SQL查询,是SQL语句的操作对象。它与ResultSetHandler组合在一起使用可以完成大部分的数据库操作,可以设置查询结果集的封装策略,线程安全。能够大大减少编码量。

QueryRunner类提供了两类构造方法:

  • QueryRunner():创建一个与数据库无关的QueryRunner对象,在操作数据库的时候,需要手动给一个Connection对象,它可以手动控制事务(setAutoCommit(false)方法设置手动管理事物和commit()方法提交事物)。
  • QueryRunner(DataSource ds): 创建一个与数据库关联的QueryRunner对象,后期再操作数据库的时候,不需要Connection对象,自动管理事务。DataSource是数据库连接池对象。

ResultSetHandler接口

该接口用于处理 java.sql.ResultSet,将数据按要求转换为另一种形式。
ResultSetHandler 接口提供了一个单独的方法:Object handle (java.sql.ResultSet .rs)

ResultSetHandler 接口的实现类
  • ArrayHandler:把结果集中的第一行数据转成对象数组。

  • ArrayListHandler:把结果集中的每一行数据都转成一个数组,再存放到List中。

  • BeanHandler:将结果集中的第一行数据封装到一个对应的JavaBean实例中。

  • BeanListHandler:将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List里。

  • ColumnListHandler:将结果集中某一列的数据存放到List中。

  • KeyedHandler(name):将结果集中的每一行数据都封装到一个Map里,再把这些map再存到一个map里,其key为指定的key。

  • MapHandler:将结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值。

  • MapListHandler:将结果集中的每一行数据都封装到一个Map里,然后再存放到List

update方法

用来执行一个更新(插入、更新或删除)操作。

int update(Connection conn, String sql)

int update(Connection conn, String sql, Object... params)

int update(String sql)

int update(String sql, Object... params)

测试update方法,步骤如下:
1. 要创建一个QueryRunner类的对象
2. 创建sql语句
3. 建立Connection连接(使用C3P0数据源)
4. 调用QueryRunner对象的update方法

    /**
     * 测试QueryRunner类的update方法
     */
    @Test
    public void testQueryRunnerUpdate() {
        //1. 创建QueryRunner的实现类
        QueryRunner queryRunner = new QueryRunner();
        String sql = "DELETE FROM customers WHERE id IN (?,?)";
        Connection connection = null;
        try {
            connection = JDBCTools.getConnection();
            //2. 使用其update方法
            queryRunner.update(connection,sql,9,10);

        } catch (SQLException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCTools.releaseDB(null,null,connection);
        }
    }

query方法

query方法的API

执行一个查询操作。

<T> T   query(Connection conn, String sql, ResultSetHandler<T> rsh)

<T> T   query(Connection conn, String sql, ResultSetHandler<T> rsh, Object... params)

<T> T   query(String sql, ResultSetHandler<T> rsh)

<T> T   query(String sql, ResultSetHandler<T> rsh, Object... params)

query方法的工作原理

下面我们来看一组测试代码:

    //创建一个QueryRunner的对象
    QueryRunner queryRunner = new QueryRunner();

    //一个内部类继承ResultSetHandler,实现handle函数
    class MyResultSetHandler implements ResultSetHandler{
        public Object handle(ResultSet resultSet) {
            System.out.println("handle....");
            return "hahaha";
        }
    }

    //QueryRunner 的 quey方法的返回值取决于其ResultSetHandler参数的handle方法的返回值
    @Test
    public void testQuery() {
        Connection connection = null;
        try {
            connection = JDBCTools.getConnection();
            String sql = "SELECT id,name,email,birth FROM customers";
            //QueryRunner对象的query函数,传递三个参数,并有一个返回值
            Object object = queryRunner.query(connection,sql,new MyResultSetHandler());
            System.out.println(object);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCTools.releaseDB(null,null,connection);
        }
    }

//

分析:

我们有一个QueryRunner类,这个类有一个query方法:

query(Connection conn,String sql,ResultSetHandler rsh) {
    //获取连接和操作sql的对象
    stmt = this.prepareStatement(conn, sql);
    //填充占位符
    this.fillStatement(stmt, params);
    //进行查询,获取结果集对象
    rs = this.wrap(stmt.executeQuery());

    //调用传入的ResultSetHandler对象的handle方法,并且把前面得到的ResultSet对象作为参数传入
    result = rsh.handle(rs);

    //把result作为结果返回
    return result;
}

那么我们在以上代码中MyResultSetHandler类的handle方法中,并没有处理传入的ResultSet对象,而是直接返回了一个字符串。因此query(Connection conn,String sql,ResultSetHandler rsh)方法中返回的就是字符串。

因此我们得到一个重要的结论:

QueryRunner 的 quey方法的返回值取决于其ResultSetHandler参数的handle方法的返回值

handle方法的功能

因此我们重新写一下MyResultSetHandler类的handle方法,令其查询结果集,并将每一条结果集得到的列作为参数传递给对象的构造函数,并加入到集合中。最终返回集合:

class MyResultSetHandler implements ResultSetHandler{
        public Object handle(ResultSet resultSet) throws SQLException {
            List<Customer> customers = new ArrayList<>();
            while (resultSet.next()) {
                Integer id = resultSet.getInt(1);
                String name = resultSet.getString(2);
                String email = resultSet.getString(3);
                String birth = resultSet.getString(4);

                Customer customer = new Customer(id,name,email,birth);
                customers.add(customer);
            }
            return customers;
        }
    }

我们重新梳理一下QueryRunner类的query方法:
1. Object object = queryRunner.query(connection,sql,new MyResultSetHandler());该方法返回一个对象
2. query(Connection conn,String sql,ResultSetHandler rsh)方法第三个参数是ResultSetHandler的一个对象
3. ResultSetHandler对象的作用是调用这个对象的handle方法,用这个方法来处理结果集
4. 因此我们要在handle方法中写入对结果集的处理

实用的Handler方法

BeanHandler()

BeanHandler:把结果集的第一条记录转为创建BeanHandler对象时传入的Class参数对应的对象,返回的是处理完的对象

public void testBeanHandler() {
        Connection connection = null;
        try {
            connection = JDBCTools.getConnection();
            String sql = "SELECT id,name,email,birth FROM customers WHERE id = ?";
            //BeanHandler传入的参数为Customer.class
            Customer customer = queryRunner.query(connection,sql,
                    new BeanHandler<Customer>(Customer.class),5);
            System.out.println(customer);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCTools.releaseDB(null,null,connection);
        }
    }
BeanListHandler()

BeanListHandler:把结果集转为一个List,该List不为null,但可能为空集合(size()方法返回0)

若SQL语句的确能够查询到记录,List中存放创建BeanListHandler传入的Class对象对应的对象。

public void testBeanListHandler() {
        Connection connection = null;
        try {
            connection = JDBCTools.getConnection();
            String sql = "SELECT id,name,email,birth FROM customers";
            //BeanListHandler传入的Class对象
            List<Customer> customers = queryRunner.query(connection,sql,new BeanListHandler<Customer>(Customer.class));
            System.out.println(customers);

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCTools.releaseDB(null,null,connection);
        }
    }
MapHandler()

MapHandler():返回SQL对应的第一条记录对应的map对象

键:SQL查询的列名(不是别名),值:列的值

@Test
    public void testMapHandler() {
        Connection connection = null;
        try {
            connection = JDBCTools.getConnection();
            String sql = "SELECT id,name,email,birth FROM customers";
            //直接传入MapHandler()对象
            Map<String,Object> customers = queryRunner.query(connection,sql,new MapHandler());
            System.out.println(customers);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCTools.releaseDB(null,null,connection);
        }
    }
MapListHandler()

MapListHandler():将结果集转为一个Map的List,Map对应查询的一条记录

键:SQL查询的列名(不是别名),值:列的值。

而MapListHandler返回的是多条记录对应的Map的集合。且在MapListHandler()的handle方法中,直接对集合进行了循环添加。

@Test
    public void testMapListHandler() {
        Connection connection = null;
        try {
            connection = JDBCTools.getConnection();
            String sql = "SELECT id,name,email,birth FROM customers";
            List<Map<String,Object>> customers = queryRunner.query(connection,sql,new MapListHandler());
            System.out.println(customers);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCTools.releaseDB(null,null,connection);
        }
    }
ScalarHandler

ScalarHandler:把结果集转为一个数值(可以是任意基本数据类型和字符串,Date等),返回

@Test
    public void testScalarHandler() {
        Connection connection = null;
        try {
            connection = JDBCTools.getConnection();
            String sql = "SELECT COUNT(id) FROM customers";
            Object result = queryRunner.query(connection,sql,
                    new ScalarHandler<>());
            System.out.println(result);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCTools.releaseDB(null,null,connection);
        }
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目标检测(Object Detection)是计算机视觉领域的一个核心问题,其主要任务是找出图像中所有感兴趣的目标(物体),并确定它们的类别和位置。以下是对目标检测的详细阐述: 一、基本概念 目标检测的任务是解决“在哪里?是什么?”的问题,即定位出图像中目标的位置并识别出目标的类别。由于各类物体具有不同的外观、形状和姿态,加上成像时光照、遮挡等因素的干扰,目标检测一直是计算机视觉领域最具挑战性的任务之一。 二、核心问题 目标检测涉及以下几个核心问题: 分类问题:判断图像中的目标属于哪个类别。 定位问题:确定目标在图像中的具体位置。 大小问题:目标可能具有不同的大小。 形状问题:目标可能具有不同的形状。 三、算法分类 基于深度学习的目标检测算法主要分为两大类: Two-stage算法:先进行区域生成(Region Proposal),生成有可能包含待检物体的预选框(Region Proposal),再通过卷积神经网络进行样本分类。常见的Two-stage算法包括R-CNN、Fast R-CNN、Faster R-CNN等。 One-stage算法:不用生成区域提议,直接在网络中提取特征来预测物体分类和位置。常见的One-stage算法包括YOLO系列(YOLOv1、YOLOv2、YOLOv3、YOLOv4、YOLOv5等)、SSD和RetinaNet等。 四、算法原理 以YOLO系列为例,YOLO将目标检测视为回归问题,将输入图像一次性划分为多个区域,直接在输出层预测边界框和类别概率。YOLO采用卷积网络来提取特征,使用全连接层来得到预测值。其网络结构通常包含多个卷积层和全连接层,通过卷积层提取图像特征,通过全连接层输出预测结果。 五、应用领域 目标检测技术已经广泛应用于各个领域,为人们的生活带来了极大的便利。以下是一些主要的应用领域: 安全监控:在商场、银行
目标检测(Object Detection)是计算机视觉领域的一个核心问题,其主要任务是找出图像中所有感兴趣的目标(物体),并确定它们的类别和位置。以下是对目标检测的详细阐述: 一、基本概念 目标检测的任务是解决“在哪里?是什么?”的问题,即定位出图像中目标的位置并识别出目标的类别。由于各类物体具有不同的外观、形状和姿态,加上成像时光照、遮挡等因素的干扰,目标检测一直是计算机视觉领域最具挑战性的任务之一。 二、核心问题 目标检测涉及以下几个核心问题: 分类问题:判断图像中的目标属于哪个类别。 定位问题:确定目标在图像中的具体位置。 大小问题:目标可能具有不同的大小。 形状问题:目标可能具有不同的形状。 三、算法分类 基于深度学习的目标检测算法主要分为两大类: Two-stage算法:先进行区域生成(Region Proposal),生成有可能包含待检物体的预选框(Region Proposal),再通过卷积神经网络进行样本分类。常见的Two-stage算法包括R-CNN、Fast R-CNN、Faster R-CNN等。 One-stage算法:不用生成区域提议,直接在网络中提取特征来预测物体分类和位置。常见的One-stage算法包括YOLO系列(YOLOv1、YOLOv2、YOLOv3、YOLOv4、YOLOv5等)、SSD和RetinaNet等。 四、算法原理 以YOLO系列为例,YOLO将目标检测视为回归问题,将输入图像一次性划分为多个区域,直接在输出层预测边界框和类别概率。YOLO采用卷积网络来提取特征,使用全连接层来得到预测值。其网络结构通常包含多个卷积层和全连接层,通过卷积层提取图像特征,通过全连接层输出预测结果。 五、应用领域 目标检测技术已经广泛应用于各个领域,为人们的生活带来了极大的便利。以下是一些主要的应用领域: 安全监控:在商场、银行
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值