精华内容
下载资源
问答
  • DBUtils

    2019-11-10 11:38:37
    DBUtils 简介 DBUtils是Java编程中的数据库操作实用工具,小巧简单实用。DBUtils封装了对JDBC的操作,简化了JDBC操作,可以减少60%以上的代码。 DBUtils三个核心功能介绍 QueryRunner:r核心类提供对sql语句操作的...

    DBUtils

    简介

    DBUtils是Java编程中的数据库操作实用工具,小巧简单实用。DBUtils封装了对JDBC的操作,简化了JDBC操作,可以减少60%以上的代码。

    DBUtils三个核心功能介绍

    • QueryRunner:核心类提供对sql语句操作的API
      • QueryRunner(DataSourcr ds):提供数据源(连接池),DbUtils底层自动维护连接connection
      • update(String sql,Obj…params):执行更新操作
      • query(String sql,ResultSetHandlerrsh,Object…panrams):执行查询操作
    • ResultSetHandler:结果集处理类,用于定义select操作后,怎样封装结果集
      • ArrayHandler:把查询结果集中的第一行数据放到一个数组中。适合取1条记录。
      • ArrayListHandler:将查询的结果的每一行数据都放到一个数组中,然后再将数组放到集合List中。适合取多条记录。
      • BeanHandler:将结果集中的第一行数据封装到一个对应的JavaBean实例中
      • BeanListHandler:将结果集中的每一行数据都封装到一个对应的JavaBean实例中,然后再将这些对象存放到List里。
      • MapHandler:将结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值。
      • MapListHandler:将查询的结果的每一行存入到一个map中,键为列名,值为各列值;然后再将map存入list中
      • ColumnListHandler:将结果集中某一列的数据存放到List中。
      • KeyedHandler(name):将结果集中的每一行数据都封装到一个Map里(List),再把这些map再存到一个map里,其key为指定的列。
      • ScalarHandler:将结果集第一行的某一列放到某个对象中。//重点
    • DBUtils:工具类,定义了关闭资源与事务处理的方法。

    示例:采用Druid和dbutils实现对Dept的CRUD

    • 第一步:Dept.java:Dept源代码

    • 第二步:新建项目,加入Maven依赖:

      <dependency>
        <groupId>commons-dbutils</groupId>
        <artifactId>commons-dbutils</artifactId>
        <version>1.7</version>
      </dependency>
      <dependency>
          <groupId>com.alibaba</groupId>
          <artifactId>druid</artifactId>
          <version>1.1.17</version>
      </dependency>
      
    • 第二步:在resources目录下创建mysql.properties,代码如下:

      driverClassName=com.mysql.cj.jdbc.Driver
      url=jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=UTC&user=root&password=&useUnicode=true&characterEncoding=UTF8&autoReconnect=true&failOverReadOnly=false
      username=root
      password=root
      
      
      filters=stat
      initialSize=2
      maxActive=300
      maxWait=60000
      timeBetweenEvictionRunsMillis=60000
      minEvictableIdleTimeMillis=300000
      validationQuery=SELECT 1
      testWhileIdle=true
      testOnBorrow=false
      testOnReturn=false
      poolPreparedStatements=false
      maxPoolPreparedStatementPerConnectionSize=200
      
    • 第三步:创建数据库连接工具类:

      public class DBUtil {
          private static final ThreadLocal<Connection> threadLocal = new ThreadLocal<>();
          private static DataSource dataSource = null;
      
          private DBUtil() {
          }
      
          static {    //配置文件加载,只执行一次
              try (InputStream is = DBUtil.class.getResourceAsStream("/mysql.properties");) {
                  Properties properties = new Properties();
                  properties.load(is);
                  dataSource = DruidDataSourceFactory.createDataSource(properties);
              } catch (Exception e1) {
                  throw new RuntimeException("读取配置文件异常", e1);
              }
          }
      
          public static Connection getConnection() {    //获取连接
              Connection conn = null;
              try {
                  conn = threadLocal.get();   //从当前线程获得 conn
                  if (conn == null || conn.isClosed()) {
                      conn = dataSource.getConnection();
                      threadLocal.set(conn);
                  }
              } catch (Exception e) {
                  throw new RuntimeException("连接数据库异常", e);
              }
              return conn;
          }
      
          public static QueryRunner getQueryRunner() {
              return new QueryRunner(dataSource);
          }
      
          public static void release(Connection conn) {
              try { // 建议采用这种形式来释放资源,因为finally里面的一定会被释放
                  if (conn != null) {
                      conn.close();
                  }
              } catch (SQLException e) {
                  e.printStackTrace();
              }
          }
      }
      
    • 第四步:测试事务

      public static void main(String[] args) {
          Connection conn = getConnection();
          try {
              conn.setAutoCommit(false); // 设置事务提交为手动
              String sql = "insert into tb_dept (dname,loc) values(?,?)";
              QueryRunner queryRunner = getQueryRunner();
              queryRunner.update(conn, sql, "aa", "aaaaa");
              System.out.println(3 / 0);
              queryRunner.update(sql, "bb", "bbbbbbbbbb");
              conn.commit();
          } catch (SQLException e) {
              e.printStackTrace();
              try {
                  conn.rollback();
              } catch (SQLException ex) {
                  ex.printStackTrace();
              }
          } finally {
              release(conn);
          }
      }
      
    • 第五步:DeptDaoImpl.java

      public class DeptDaoImpl {
          private QueryRunner queryRunner = DBUtil.getQueryRunner();
      
          public int insertDept(Dept dept) throws SQLException {
              String sql = "insert into tb_dept (deptno, dname, loc) values (?, ?, ?)";
              return queryRunner.update(sql, dept.getDeptno(), dept.getDname(), dept.getLoc());
          }
      
          public int batchInsertDept(List<Dept> deptList) throws SQLException {
              Object[][] params = new Object[deptList.size()][3];
      
              for (int i = 0; i < params.length; i++) {
                  Dept dept = deptList.get(i);
                  params[i][0] = dept.getDeptno();
                  params[i][1] = dept.getDname();
                  params[i][2] = dept.getLoc();
              }
      
              StringBuilder wenHao = new StringBuilder();
              for (int i = 0; i < params[0].length; i++) {
                  wenHao.append("?,");
              }
              String sql = "insert into tb_dept values(" + wenHao.deleteCharAt(wenHao.length() - 1) + ")";
      
              queryRunner.batch(sql, params);
              return 1;  // 如果不抛出异常,就返回1,表示删除成功
          }
      
          public int deleteDeptByDeptno(Byte deptno) throws SQLException {
              String sql = "delete from tb_dept where deptno = ?";
              return queryRunner.update(sql, deptno);
          }
      
          public int deleteDeptByCondition(Dept dept) throws SQLException {
              List<Object> paramValueList = new ArrayList<>();
              StringBuffer paramBuf = new StringBuffer("1=1 ");
      
              if (dept.getDeptno() != null) {
                  paramBuf.append("and deptno= ? ");
                  paramValueList.add(dept.getDeptno());
              }
              if (dept.getDname() != null) {
                  paramBuf.append("and dname= ? ");
                  paramValueList.add(dept.getDname());
              }
              if (dept.getLoc() != null) {
                  paramBuf.append("and loc= ? ");
                  paramValueList.add(dept.getLoc());
              }
      
              String sql = "delete from tb_dept where " + paramBuf.substring(0, paramBuf.length() - 3);
              return queryRunner.update(sql, paramValueList.toArray());
          }
      
          public int batchDeleteDeptByDeptnos(String deptnos) throws SQLException {
              String[] split = deptnos.split(",");
              Object[][] params = new Object[1][];
      
              StringBuilder wenHao = new StringBuilder();
              for (int i = 0; i < split.length; i++) {
                  wenHao.append("?,");
              }
              params[0] = split;
      
              String sql = "delete from tb_dept where deptno in (" + wenHao.deleteCharAt(wenHao.length() - 1) + ")";
      
              queryRunner.batch(sql, params);
              return 1;  // 如果不抛出异常,就返回1,表示删除成功
          }
      
          public int updateDept(Dept dept) throws SQLException {
              String sql = "update tb_dept set dname= ? ,loc= ? where deptno = ?";
              return queryRunner.update(sql, dept.getDname(), dept.getLoc(), dept.getDeptno());
          }
      
          public long selectCount() throws SQLException {
              String sql = "select count(*) from tb_dept";
              // ScalarHandler:将查询的结果的第一行的某一列放到一个对象中;精确定位到某个值
              Long query = queryRunner.query(sql, new ScalarHandler<Long>());
              return query.intValue();
          }
      
          public long selectCountByCondition(Dept dept) throws SQLException {
              List<Object> paramValueList = new ArrayList<>();
              StringBuffer paramBuf = new StringBuffer("1=1 ");
      
              if (dept.getDeptno() != null) {
                  paramBuf.append("and deptno= ? ");
                  paramValueList.add(dept.getDeptno());
              }
              if (dept.getDname() != null) {
                  paramBuf.append("and dname= ? ");
                  paramValueList.add(dept.getDname());
              }
              if (dept.getLoc() != null) {
                  paramBuf.append("and loc= ? ");
                  paramValueList.add(dept.getLoc());
              }
      
              String sql = "select count(*) from tb_dept where " + paramBuf.substring(0, paramBuf.length() - 3);
              Long query = queryRunner.query(sql, new ScalarHandler<Long>(), paramValueList.toArray());
              return query.intValue();
          }
      
          public Dept selectDeptByDeptno(Byte deptno) throws SQLException {
              String sql = "select deptno as deptno, dname as dname, loc as loc from tb_dept where  deptno = ?";
              return queryRunner.query(sql, new BeanHandler<>(Dept.class), deptno);
          }
      
          public List<Dept> selectAllDept() throws SQLException {
              String sql = "select deptno as deptno, dname as dname, loc as loc from tb_dept";
              return queryRunner.query(sql, new BeanListHandler<>(Dept.class));
          }
      
          public List<Dept> selectDeptByCondition(Dept dept) throws SQLException {
              List<Object> paramValueList = new ArrayList<>();
              StringBuffer paramBuf = new StringBuffer("1=1 ");
      
              if (dept.getDeptno() != null) {
                  paramBuf.append("and deptno= ? ");
                  paramValueList.add(dept.getDeptno());
              }
              if (dept.getDname() != null) {
                  paramBuf.append("and dname= ? ");
                  paramValueList.add(dept.getDname());
              }
              if (dept.getLoc() != null) {
                  paramBuf.append("and loc= ? ");
                  paramValueList.add(dept.getLoc());
              }
      
              String sql = "select deptno as deptno, dname as dname, loc as loc  from tb_dept where " + paramBuf.substring(0, paramBuf.length() - 3);
              return queryRunner.query(sql, new BeanListHandler<>(Dept.class), paramValueList.toArray());
          }
      
          public List<Dept> selectDeptWithPagination(int page, int rows) throws SQLException {
              String sql = "select deptno as deptno, dname as dname, loc as loc from tb_dept limit ?, ?";
              return queryRunner.query(sql, new BeanListHandler<>(Dept.class), (page - 1) * rows, rows);
          }
      
          public List<Dept> selectDeptWithPaginationByCondition(int page, int rows, Dept dept) throws SQLException {
              List<Object> paramValueList = new ArrayList<>();
              StringBuffer paramBuf = new StringBuffer("1=1 ");
      
              if (dept.getDeptno() != null) {
                  paramBuf.append("and deptno= ? ");
                  paramValueList.add(dept.getDeptno());
              }
              if (dept.getDname() != null) {
                  paramBuf.append("and dname= ? ");
                  paramValueList.add(dept.getDname());
              }
              if (dept.getLoc() != null) {
                  paramBuf.append("and loc= ? ");
                  paramValueList.add(dept.getLoc());
              }
      
              String sql = "select deptno as deptno, dname as dname, loc as loc  from tb_dept where " + paramBuf.substring(0, paramBuf.length() - 3) + " limit ?, ?";
      
              paramValueList.add((page - 1) * rows);
              paramValueList.add(rows);
              return queryRunner.query(sql, new BeanListHandler<>(Dept.class), paramValueList.toArray());
          }
      }
      

    动态SQL与静态SQL

    SQL 语句从编译和运行的角度可以分为静态 SQL和 动态 SQL,所谓SQL的动态和静态,是指SQL语句在何时被编译和执行。

    这两种 SQL 在使用方式、运行机制和性能表现等方面各有特点 :

    • 静态 SQL:静态 SQL 语句一般用于嵌入式 SQL 应用中,在程序运行前,SQL 语句在编程时候必须是确定好的,例如 SQL 语句中涉及的列名和表名必须是存在的。静态 SQL 语句的编译是在应用程序运行前进行的,编译的结果会存储在数据库内部。而后程序运行时,数据库将直接执行编译好的 SQL 语句,降低运行时的开销。
    • 动态 SQL:动态 SQL 语句是在应用程序运行时被编译和执行的,例如,使用 DB2 的交互式工具 CLP 访问数据库时,用户输入的 SQL 语句是不确定的,因此 SQL 语句只能被动态地编译。动态 SQL 的应用较多,常见的 CLI 和 JDBC 应用程序都使用动态 SQL。

    静态sql的存取路径是在运行前就确定好的,而动态sql的存取路径是在运行时动态生成的。

    注意:在SQL中如果某些参数没有确定,如"select * from t1 where c1>? and c2<?",这种语句是静态SQL,不是动态SQL,虽然个别参数的值不知道,但整个SQL的结构已经确定,数据库是可以将它编译的,在执行阶段只需将个别参数的值补充进来即可。

    展开全文
  • DbUtils

    2020-03-26 23:58:16
    DbUtils 1. 轻量级数据库ORM框架DbUtils 1.1 DbUtils介绍 Apache组织下的一个轻量级ORM框架 Commons DbUtils: JDBC Utility Component 两个核心方法 update方法 ==> insert,update,delete query方法 ==>...

    DbUtils

    1. 轻量级数据库ORM框架DbUtils

    1.1 DbUtils介绍
    	Apache组织下的一个轻量级ORM框架
    	Commons DbUtils: JDBC Utility Component
    两个核心方法
    	update方法 ==> insert,update,delete
    	query方法 ==> select
    
    一个核心类
    	QueryRunner DbUtils的核心类
    
    1.2 DbUtils ORM工具使用
    package com.qfedu.c_dbutils;
    
    import com.qfedu.b_studentsys.entity.Student;
    import org.apache.commons.dbutils.QueryRunner;
    import org.apache.commons.dbutils.ResultSetHandler;
    import org.apache.commons.dbutils.handlers.*;
    import org.junit.Test;
    import util.JdbcUtil;
    
    import java.sql.Connection;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.util.Arrays;
    import java.util.List;
    import java.util.Map;
    
    /**
     * DbUtils ORM框架演示
     *
     * @author Anonymous 2020/3/25 16:03
     */
    public class DbUtilsTest {
        @Test
        public void testInsert() throws SQLException {
            // 1. DbUtils核心类 QueryRunner对象
            QueryRunner runner = new QueryRunner();
    
            // 2. 插入数据到Student数据表中
            String sql = "insert into student(name, age, gender, score, address) value(?, ?, ?, ?, ?)";
            Object[] parameters = {"老黑", 70, true, 59, "河南郑州"};
    
            // 3. 获取数据库连接
            Connection connection = JdbcUtil.getConnection();
    
            // 4. 执行Update方法
            runner.update(connection, sql, parameters);
    
            JdbcUtil.close(connection);
        }
    
        /**
         * 了解操作方式, ResultSetHandler
         */
        @Test
        public void testQuery1() throws SQLException {
            // 1. DbUtils核心类 QueryRunner对象
            QueryRunner runner = new QueryRunner();
    
            // 2. SQL语句
            String sql = "select * from student where id = 1";
    
            Connection connection = JdbcUtil.getConnection();
    
            /*
             ResultSetHandler 核心接口
                ResultSet结果集 Handler处理,
                核心方法 handler(ResultSet rs)
             */
            Student student = runner.query(connection, sql, rs -> {
                Student stu = null;
                if (rs.next()) {
                    int id = rs.getInt("id");
                    String name = rs.getString("name");
                    int age = rs.getInt("age");
                    boolean gender = rs.getBoolean("gender");
                    float score = rs.getFloat("score");
                    String address = rs.getString("address");
    
                    stu = new Student(id, name, age, gender, score, address);
                }
                return stu;
            });
    
            System.out.println(student);
            JdbcUtil.close(connection);
        }
    
        /**
         * BeanHandler
         */
        @Test
        public void queryBean() throws SQLException {
            // 1. DbUtils核心类 QueryRunner对象
            QueryRunner runner = new QueryRunner();
    
            // 2. SQL语句
            String sql = "select * from student where id = 1";
    
            Connection connection = JdbcUtil.getConnection();
    
            /*
            BeanHandler: 处理符合JavaBean规范的类对象,传入参数是对应JavaBean规范 Class对象
             */
            Student student = runner.query(connection, sql, new BeanHandler<>(Student.class));
    
            System.out.println(student);
    
            JdbcUtil.close(connection);
        }
    
        /**
         * BeanListHandler
         */
        @Test
        public void queryBeanList() throws SQLException {
            // 1. DbUtils核心类 QueryRunner对象
            QueryRunner runner = new QueryRunner();
    
            // 2. SQL语句
            String sql = "select * from student where id > ?";
    
            Connection connection = JdbcUtil.getConnection();
    
            /*
            BeanListHandler: 处理符合JavaBean规范的实体类,并且返回值是一个List集合
            包含制定的JavaBean实体类
             */
            List<Student> list = runner.query(connection, sql, new BeanListHandler<>(Student.class), 2);
    
            for (Student student : list) {
                System.out.println(student);
            }
            JdbcUtil.close(connection);
        }
    
        /**
         * ArrayHandler
         */
        @Test
        public void queryArray() throws SQLException {
            // 1. DbUtils核心类 QueryRunner对象
            QueryRunner runner = new QueryRunner();
    
            // 2. SQL语句
            String sql = "select * from student where id = 1";
    
            Connection connection = JdbcUtil.getConnection();
    
            /*
            ArrayHandler: 查询一个数据行,数据行中的所有数据整合成一个Object类型数组返回
             */
            Object[] values = runner.query(connection, sql, new ArrayHandler());
    
            System.out.println(Arrays.toString(values));
    
            JdbcUtil.close(connection);
        }
    
        /**
         * ArrayListHandler
         */
        @Test
        public void queryArrayList() throws SQLException {
            // 1. DbUtils核心类 QueryRunner对象
            QueryRunner runner = new QueryRunner();
    
            // 2. SQL语句
            String sql = "select * from student where id > ?";
    
            Connection connection = JdbcUtil.getConnection();
    
            /*
            ArrayListHandler: 查询结果集中所有数据行,每一行数据对应一个Object类型数组,存储在List集合中
             */
            List<Object[]> list = runner.query(connection, sql, new ArrayListHandler(), 2);
    
            for (Object[] values : list) {
                System.out.println(Arrays.toString(values));
            }
            JdbcUtil.close(connection);
        }
    
        /**
         * MapHandler
         */
        @Test
        public void queryMap() throws SQLException {
            // 1. DbUtils核心类 QueryRunner对象
            QueryRunner runner = new QueryRunner();
    
            // 2. SQL语句
            String sql = "select * from student where id = 1";
    
            Connection connection = JdbcUtil.getConnection();
    
            /*
            MapHandler: 处理一个数据行,数据行中字段是对应Key,字段对应数据是value,组成一个Map双边队列
             */
            Map<String, Object> map = runner.query(connection, sql, new MapHandler());
    
            System.out.println(map);
        }
    
        /**
         * MapListHandler
         */
        @Test
        public void queryMapList() throws SQLException {
            // 1. DbUtils核心类 QueryRunner对象
            QueryRunner runner = new QueryRunner();
    
            // 2. SQL语句
            String sql = "select * from student where id > ?";
    
            Connection connection = JdbcUtil.getConnection();
    
            /*
            MapListHandler: 结果集中所有的数据行,每一行对应一个Map对象,字段名为Key,字段对应的数据为value,所有数据行存储
            在List中
             */
            List<Map<String, Object>> mapList = runner.query(connection, sql, new MapListHandler(), 2);
    
            for (Map<String, Object> map : mapList) {
                System.out.println(map);
            }
        }
    }
    
    
    1.3 ResultHandler以及其子类
    ResultSetHandler 核心接口
    	ResultSet结果集 Handler处理,	
    	核心方法 handler(ResultSet rs)
     
    BeanHandler: 
    	处理符合JavaBean规范的类对象,传入参数是对应JavaBean规范 Class对象
    
    BeanListHandler: 
    	处理符合JavaBean规范的实体类,并且返回值是一个List集合包含制定的JavaBean实体类
    
    ArrayHandler: 
    	查询一个数据行,数据行中的所有数据整合成一个Object类型数组返回
    
    ArrayListHandler: 
    	查询结果集中所有数据行,每一行数据对应一个Object类型数组,存储在List集合中
    
    MapHandler: 
    	处理一个数据行,数据行中字段是对应Key,字段对应数据是value,组成一个Map双边队列
    
    MapListHandler: 
    	结果集中所有的数据行,每一行对应一个Map对象,字段名为Key,字段对应的数据为value,所有数据行存储在List中
    
    展开全文
  • DButils

    千次阅读 2018-07-30 11:12:36
    Dbutils是什么?(当我们很难理解一个东西的官方解释的时候,就让我们记住它的作用) Dbutils:主要是封装了JDBC的代码,简化dao层的操作。 作用:帮助java程序员,开发Dao层代码的简单框架。 为什么需要Dbutils...

    Dbutils是什么?(当我们很难理解一个东西的官方解释的时候,就让我们记住它的作用)
    Dbutils:主要是封装了JDBC的代码,简化dao层的操作。
    作用:帮助java程序员,开发Dao层代码的简单框架。
    为什么需要Dbutils ?
    在使用Dbutils 之前,我们Dao层使用的技术是JDBC,那么分析一下JDBC的弊端:
    (1)数据库链接对象、sql语句操作对象,封装结果集对象,这三大对象会重复定义
    (2)封装数据的代码重复,而且操作复杂,代码量大
    (3)释放资源的代码重复
    结果:
    (1)程序员在开发的时候,有大量的重复劳动。(
    (2)2)开发的周期长,效率低

    使用Dbutils注意事项:
    (1)需要导入的jar包
    (2)添加c3p0配置文件
    (3)可以自行添加一个JDBCUtils工具类:用来获取c3p0连接池对象

    使用前查询指定的账号信息:
    这里写图片描述

    使用后的获取指定的账号信息:
    这里写图片描述
    用这个:
    这里写图片描述
    代替:

    这里写图片描述

    这里写图片描述

    new BeanHandler<User>(User.class),params

    (BeanHandler类)
    代表:

    if (rs.next()){
        User user = new User();
        user.setUserId(rs.getString("userId"));//从结果集当前记录中取出userId
        user.setPassword(rs.getString("password"));
        user.setName(rs.getString("name"));
        user.setPhone(rs.getString("phone"));
        user.setSex(rs.getByte("sex"));
        return user;

    DbUtils 关闭链接等操作
    QueryRunner 进行查询的操作
    ArrayHandler :将ResultSet中第一行的数据转化成对象数组
    ArrayListHandler将ResultSet中所有的数据转化成List,List中存放的是Object[]
    BeanHandler :将ResultSet中第一行的数据转化成类对象
    BeanListHandler :将ResultSet中所有的数据转化成List,List中存放的是类对象
    ColumnListHandler :将ResultSet中某一列的数据存成List,List中存放的是Object对象
    KeyedHandler :将ResultSet中存成映射,key为某一列对应为Map。Map中存放的是数据
    MapHandler :将ResultSet中第一行的数据存成Map映射
    MapListHandler :将ResultSet中所有的数据存成List。List中存放的是Map
    ScalarHandler :将ResultSet中一条记录的其中某一列的数据存成Object
    SqlNullCheckedResultSet :对ResultSet进行操作,改版里面的值
    StringTrimmedResultSet :去除ResultSet中中字段的左右空格。Trim()
    主要方法:
    DbUtils类:启动类
    ResultSetHandler接口:转换类型接口
    MapListHandler类:实现类,把记录转化成List
    BeanListHandler类:实现类,把记录转化成List,使记录为JavaBean类型的对象
    Query Runner类:执行SQL语句的类

    展开全文
  • dbutils

    2018-06-14 12:37:19
    commons-dbutils 是Apache组织提供的一个开源JDBC工具类库,它是对JDBC的简单封装,学习成本极低,并且使用dbutils能极大简化jdbc编码的工作量,同时也不会影响程序的性能,因此dbutils成为很多不喜欢hibernate的...

    介绍

    • commons-dbutils 是Apache组织提供的一个开源JDBC工具类库,它是对JDBC的简单封装,学习成本极低,并且使用dbutils能极大简化jdbc编码的工作量,同时也不会影响程序的性能,因此dbutils成为很多不喜欢hibernate的公司的首选。
    • API介绍
      • org.apache.commons.dbutils.QueryRunner–核心
      • org.apache.comons.dbutils.ResultSetHandler
      • 工具类
        • org.apache.commons.dbutils.DbUtils
    QueryRunner runner = new QueryRunner();
            List<Account> as = runner.query(JdbcUtils.getConnection(),sql,new BeanListHandler<Account>(Account.class));
    
            for(Account a : as){
               System.out.println(a);
           }

    手动封装数据

    new ResultSetHandler<List<Account>>(){
        public List<Account> handler(ResultSet rs) throws SQLException{
            List<Account> as = new ArrayList<Account>();
            while(rs.next()){
                Account a new Account();
                a.setId(rs.getInt("id"));
                a.setName(rs.getString("name"));
                a.setMoney(rs.getDouble("money"));
    
                as.add(a);
            }
            return as;
        }
    }

    dbutils 核心

    • QueryRunner 类
      • 用于执行SQL语句的类
        • query 用于执行select
        • update 用于执行update 、select、insert
        • batch 批处理
      • ResultSetHandler接口
        • 用于定义结果集的封装,实现类是BeanListHandler()见手动封装结果集)
        • 它提供了九个实现类,可以进行不同的封装
      • DbUtils 类
        • 提供关于关闭资源及事务rollback,commit 操作。

    QueryRunner类

    获取方式

    • new QueryRunner();
      • 该构造方式创建的QueryRunner,它的事务是手动控制
    • new QueryRunner(DataSource rs )
      • 该构造方式创建的QueryRuuner,它的事务是自动控制的,即一条SQL语句,一个事务。

    核心方法

    • query
    • update
    • batch
    • 对于上述三种方法,它们提供很多重载
      • 如果QueryRunner在创建时,没有床底DataSource 参数,那么在使用query ,update,batch方法时,要传递connection 参数
      • 如果在创建QueryRunner 时,传递了DataSource参数,那么在使用query,update,batch方法时,不需要传递connection参数。
    public void fun1(){
        String sql = "select * from account";
        QueryRunner runner = new QueryRunner();//事务手动控制
    
        Connection con = DataSourceUtils.getConnection();
        List<Account> list = runner.query(con,sql,new BeanListHandler<Account>(Account.class));//需要传递con 参数
    
    }
    public void fun2(){
        String sql = "select * from account";
        QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());//自动事务
       List<Account> list = runner.query(sql,new BeanListHandler<Account>(Account.class));//不需要传递con
    }

    总结

    QueryRunner runner = new QueryRunner();
    runner.query(Connection,sql,ResultSetHandler,Object...param);
    runner.update(Connection,sql,Object...param);
    runner.batch(Connection con,sql,Object[][] objs);
    
    QueryRunner runner = new QueryRunner(DataSource ds);
    runner.query(sql,ResultSetHandler,Object...param);
    runner.update(sql,Object...param);
    runner.batch(sql,Object[][] objs);

    ResultSetHandler接口

    public void fun1() throws SqLException{
        String sql = "select * from account where id=?";
        QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
        Account a = runner.query(sql,new ResultSetHandler<Account>(){//ResultSetHandler上的泛型就是我们执行query方法后得到的结果
    //重写handle方法,在这个方法中确定,怎样将结果集封装
            public Account handle(ResultSet rs) throws SQLException{
                Account a = null;
                if(rs.next()){
                    a=new Account();
                    a.setId(rs.getInt("id"));
                    a.setName(rs.getString("name"));
                    a.setMoney(rs.getDouble("money"));
                }
                return a;
            }
        },2);
    
        System.out.println(a);  
    }

    模仿QueryRunner方法

    public class MyQueryRunner{
        //执行select操作
        public Object query(){
            return null;
        }
        //执行update操作
        public int update(Connection con,String sql,Object ...params){
            PreparedStatement pst = con.prepareStatement(sql);//得到一个预处理的Statement
            //问题:SQL语句中可能存在参数,需要对参数赋值
    
            ParameterMetaData pmd= pst.getParameterMetaData();
            //可以得到有几个参数
            int count = pmd.getParameterCount();
            for(int i=1;i<=count;i++){
                pst.setObject(i,params[i-1]);
            }
    
            return pst.executeUpdate();
        }
    }

    ResultSetHandler的九个实现类

    ArrayHandler
    将结果集中的第一条记录封装到Object[],数组中的每一个元素就是记录中的字段值。

    public void fun1() throws SQLException{
    QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
    Object[] obj = runner.query("select * from account",new ArrayHandler());
    System.out.pritnln(Arrays.toString(obj));
    }

    ArrayListHandler
    将结果集中每一条记录封装到Object[],数组中的每一个元素就是记录中的字段值,再将这些数组装入到List集合。

    public void fun2() throws SQLException{
        QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
        List<Object[]> objs=runner.query("select * from account",new ArrayListHandler());
        for(Object[] obj:objs){
            System.out.println(obj);
        }
    }

    BeanHandler(重点)
    将结果集中的第一条记录封装到一个JavaBean中

    public void fun3() throws SQLException{
        QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
        Account obj = runner.query("select * from account",new Beanhandler<Account>(Account.class));
        System.out.printnln(obj);
    }

    BeanListHandler(重点)
    将结果集中的每一条记录封装到JavaBean中,再将JavaBean封装到List集合中。

    public void fun4() throws SQLException{
        QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
        List<Account> obj = runner.query("select * from account",new BeanListHandler<Account>(Account.class));
        System.out.println(obj);
    }

    ColumnListHandler
    把结果集中的指定列的值封装到了List集合里。

    public void fun5() throws SQLException{
        QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
        List<Object> obj = runner.query("select * from account",new ColumnListHandler("name"));
        System.out.println(obj);
    }

    MapHandler
    将结果集中第一条记录封装到Map集合中,集合中的key就是字段名称,value就是字段值

    public void fun6() throws SQLException{
        QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
        Map<String,Object> obj = runner.query("select * from account",new MapHandler());
        System.out.println(obj);
    }

    MapListHandler
    将结果集中每一条记录封装到Map集合中,集合中的key就是字段名称,value就是字段名值,再将这些Map封装到List集合中。

    public void fun7() throws SQLException{
        QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
        List<Map<String,Object>> obj = runner.query("select * from account",new MapListHandler());
        System.out.println(obj);
    }

    KeyedHandler
    将结果集中每一条记录封装到一个Map集合,再使用指定的列的值作为一个Map集合的key,值为每一条记录的Map集合封装。

    public void fun8() throws SQLException{
        QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
        Map<Object,Map<String,Object>> obj = runner.query("select * from account",new KeyedHandler("name"));
        System.out.println(obj);
    }

    ScalarHandler
    进行单值查询 select count(*) from account;

    public void fun9() throws SQLException{
        QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
        long obj = (long)runner.query("select count(*) from account",new ScalarHandler());
        System.out.println(obj);
        //System.out.println(obj.getCalss().getName())
    }

    模仿实现BeanHandler

    //从结果集方向封装数据
    public Object handle(ResultSet rs) throws SQLException{
        Objet obj = null;
        //得到结果集元数据
        ResultSetMetaData md = rs.getMetaData();
        //得到所有字段名称
        int count = md.getColumnCount();
    
        if(rs.nest()){
            try{
                BeanInfo bif = Introspector.getBeanInfo(clazz);//得到BeanInfo
                PropertyDescriptor[] pds = bif.getPropertyDescriptors();//得到JavaBean的所有属性描述器
                obj = clazz.newInstance();
                for(int i=1;i<=count ;i++){
                    String name = md.getColumnName(i);//得到每一列的名称
                    for(PropertyDescriptor pd:pds){
                        if(name.equals(pd.getName())){
                            pd.getWriteMethod().invoke(obj,rs.getObject(name));//使用setXXX方法将结果集中的字段值封装到JavaBean的对应属性上。
                        }
                    }
                }
            }
        }
    }

    案例演示(客户信息展示)

    客户信息

    字段名 说明 类型
    Id 编号 varchar(40)
    name 客户姓名 varchar(20)
    gender 性别 varchar(10)
    birthday 生日 date
    cellphone 手机 varchar(20)
    email 电子邮件 varchar(40)
    preference 客户爱好 varchar(100)
    type 客户类型 varchar(40)
    description 备注 varchar(255)

    创建表

    create table customer(
        id varchar(40) primary key,
        name varchar(20),
        gender varchar(10),
        birthday date,
        cellphone varchar(20),
        email varchar(40),
        preference varchar(100),
        type varchar(40),
        description varchar(255)
    );

    环境搭建

    • JavaEE 三层结构
    • Servlet +JSP + JavaBean +jstl+DBUtils+DAO+MySQL
    • 导入jar包:JSTL,BeanUtils,DBUtils,C3P0,mysql驱动
    • 创建包结构
      • cn.xd.customer.web 表现层
      • cn,xd.customer.service 业务层
      • cn.xd.customer.dao 持久层
      • cn.xd.customer.utils工具包
      • cn.xd.customer.domain实体类 (JavaBean)
    • 应用的jar包
      • MySQL驱动包
      • c3p0包
      • dbutils包
      • BeanUtil包
      • JSTL包
      • c3p0的配置文件
    • 公共程序 domain utils
    • Customer 类 实体类
    • DataSourceUtils 工具类

    编写代码

    创建Customer的JavaBean

       private String id;
        private String name;
        private String gender;
        private Date birthday;
        private String email;
        private String preference;
        private String type;
        private String description;

    为了测试方便,向customer表中插入数据

    insert into customer values("a11","tom","男","2010-10-10","1372389034","tom@163.com","吃喝玩","vip","good man");
    insert into customer values("a12","fox","男","2010-10-10","1372389034","fox@163.com","吃喝玩","vip","good man");
    insert into customer values("a13","james","男","2010-10-10","1372389034","james@163.com","吃喝玩","vip","good man");

    实现查询所有客户信息操作

    • 在success.jsp页面添加连接
      • <a href="${pageContext.request.ContextPath}/findAll">查看客户信息</a>
    • 在CustomerFindAllServlet中调用service,在service中调用dao,最后得到一个List<Customer>
    • 在showCustomer.jsp页面展示客户信息
    <c:forEach items="${cs}" var="c">
                <tr>
                    <td><input type="checkbox"></td>
                    <td>${c.id}</td>
                    <td>${c.name}</td>
                    <td>${c.gender}</td>
                    <td>${c.birthday}</td>
                    <td>${c.cellphone}</td>
                    <td>${c.email}</td>
                    <td>${c.preference}</td>
                    <td>${c.type}</td>
                    <td>${c.description}</td>
                    <td>
                        <a>编辑</a>&nbsp;&nbsp;&nbsp;<a>删除</a>
                    </td>
                </tr>
    
            </c:forEach>

    删除操作

    • 在showCustomer.jsp页面的删除连接上添加参数 客户的id
      <a>编辑</a>&nbsp;&nbsp;&nbsp;<a href="${pageContext.request.contextPath}/delById?id=${c.id}">删除</a>
    • 创建一个CustomerDelByIdServlet,完成获取请求参数,调用service中删除方法
      • 问题:如果删除完成后,怎么处理?
        • 跳转到 CustomerFindAllServlet中,再重新查询数据

    编辑

    • 查询,做回显示
      • <a href="${pageContext.req.contextPath}/findById?id=${c.id}">编辑</a>
      • 创建CustomerFindByIdServlet,得到要查询的id,调用service,得到Customer对象
      • 将customer对象存储到request域,请求转发到customerInfo.jsp页面。
      • 在customerInfo,jsp中展示客户信息
      • 注意:客户的id不能修改,所以使用<input type="hedden">
    • 修改
      • 注意使用BeanUtils时的类型转换问题
      • 注意编码问题
        • post:request.setCharacterEncoding(“utf-8”);
        • get:手动转换 new String(request.getParameter(name).getBytes(“iso8859-1”),”utf-8”)
      • 进行修改操作

    添加

    • 在showCustomer.jsp页面上添加一个连接,可以直接访问到添加页面 add.jsp
    • 创建add.jsp
      • 关于生日的日历组件
        • 导入js
        • 在input type = text组件上添加 calss,onclick
      • 关于id问题
        • 使用UUID获取
      • 创建CustomerAddServlet完添加操作
      • 得到所有请求参数封装到Customer对象
        • 编码问题
        • 使用BeanUtils,注意Date类型转换问题,
        • 手动封装id
      • 调用service完成添加操作
    <td>
        <a href="${pageContext.request.contextPath}/add.jsp">添加</a>
    </td>
    //add.jsp
    <head>
    <script language="javascript" type="text/javascript" src="${pageContext.request.contextPath}/My97DatePicker/WdatePicker.js"></script>
    </head>
    <body>
    ${requestScope["add.message"]}<br>
    <form action="${pageContext.request.contextPath}/add" method="post">
        客户姓名:<input type="text" name="name"><br>
        客户性别:<input type="radio" name="gender" value="男"><input type="radio" name="gender" value="女">女
        客户生日:<input type="text" name="birthday" class="Wdate" onclick="WdatePicker()"><br>
        客户电话:<input type="text" name="cellphone" ><br>
        客户邮箱:<input type="text" name="email" ><br>
        客户爱好:<input type="text" name="preference" ><br>
        客户类型:<input type="text" name="type" ><br>
        客户备注:<input type="text" name="description" ><br>    
        <input type="submit" value="添加">
    </form>
    </body>
    //CustomerAddServlet.java
    req.setCharacterEncoding("utf-8");
    DateConverter dc = new DateConverter();
    dc.setPattern("yyyy-MM-dd");
    try{
        ConverUtils.register(dc,java.util.Date.class);
        BeanUtils.populate(c,req.getParameterMap());
    
    }catch(IllegalAccessException e){
        e.printStackTrace();
    }catch(InvocationTargetException e){
        e.printStackTrace();
    }
    
    
    //手动将id封装到Customer对象中
    c.setId(IDUtils.getUUID());
    //调用service完成添加操作
    CustomerService service = new CustomerService();
    try{
        service.add(c);
        //添加成功
        resp.sendRedirect(req.getContextPath()+"/fondAll");
    }catch (SQLException e){
        e.printStackTrace();
        req.setAttribute("add.message","添加客户信息失败");
        req.getRequestDispatcher("/add.jsp").forward(req,resp);
        return;
    }
    
    
    //UUID示例
    public class IDUtils{
        public static String getUUID(){
            return UUID.randomUUID().toString();
        }
        public static void main(String[] args){
            System.out.println(getUUID());
        }
    }
    //CustomerService.java
    //添加客户信息
    public void add(Customer c) throws SQLException{
        dao.add(c);
    }
    //dao.java
    public void add(Customer c) throws SQLException{
        String sql="insert into customer values(?,?,?,?,?,?,?,?,?)";
        QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
        runner.update(sql,c.getId(),c.getName(),c.getGender(),c.getBirthday(),c.getCellphone(),c.getEmail(),c.getPreference(),c.getType(),c.getDescription());
    
    
    }

    批量删除

    • 完成页面上全选与全不选操作
    • 完成批量删除
      • 页面上怎样将数据提交到服务器端
        • 可以创建一个表单,,将表单数据提交
        • 直接使用js操作,需要手动拼接出url路径
      • 在服务器端怎样批量删除
        • 得到所用要删除的id值
    //showCustomer.jsp
    
    <head>
        <script>
            function change(){
                //得到id为main的checkbox
                documnet.getElementById("main");
                var flag = main.checked;
                //得到所有name=ck 的checkbox
                var cks = document.getElementsByName("ck");
                //将cks中所有的checkbox的checked值设置为flag
                for(var i=0;i<cks.length;i++){
                    cks[i].checked=flag;
                }
            }
        </script>
    
    </head>
    
    
    
    <table>
    <tr>
        <td>
            <input type="checkbox" id="main" onclick="change()">
        </td>
    </tr>
    
    <c:forEach items="${cs}" var="c">
    <tr>
        <td>
            <input type="checkbox" name="ck">
        </td>
    </tr>
    </c:forEach>
    </table>
    //showCustomer.jsp
    <script>
    //作用:让表单提交
    function sendDel(){
        document.getElementById("f").submit;//表单提交
        var cks = document.getElementsByName("ck");
      /*  var url="${pageContext.request.contextPath}/delSelect?"
        for(var i=0;i<cks.length;i++){
            if(cks[i].checked){
                var id=cks[i].value;
                url+="id="+id+"&";
            }*/
        }
    
    
    };
    </script>
    
    
    
    <c:if test ="${not empty cs}">
    <form action = "${pageContext.request.contextPath}/delSelect" method="post" id="f">
    <table>
    <c:forEach items="${cs}" var = "c">
        <tr>
            <td>
                <input type="checkbox" value="${c.id}" name="ck">
            </td>
        </tr>
    </c:forEach>
    </table>
    </form>
    </c:if>
    <tr>
        <td colspan="10"><a href="javascript:void(0)" onclick="sendDel();">删除选中</a></td>
    </tr>
    //CustomerDelSelectServlet
    
    //得到所有要删除的客户的id
    String[] id = req.getParameterCalues("ck");
    //调用service,完成批量删除
    CustomerService service = new CustomerService();
    service.delSelect(id);
    
    //CustomerService.java
    //批量删除
    public void delSelect(String[] id){
    
        dao.delSelect(id);
    }
    
    //customerDao.java
    public void delSelect(Stinf[] id){
        String sql="delete from customer where id=?";
        QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
        for(int i=0;i<id.length;i++){
            ids[i][0]=id[i];
        }
        runner.batch(sql,ids);
    
    }

    条件查询

    • 页面完成
    • 创建CustomerSimpleSelectServlet完成条件查询
    //showCustomer.jsp
    <c:if test="${not empty cs}">
        <div align ="center">
            <form action="${pageContext.request.contextPath}/simpleSelect" method="post">
            <select name="sel">
                <option>请选择条件</option>
                <option value="name">按姓名查询</option>
                <option value="cellphone">按手机号查询</option>
                <option value="gender">按性别查询</option>
            </select>
            <input type="text" name="msg">
            <input type=“submit” value="查询">
            </form>
        </div>
    </c:if>
    • 问题:select的名称叫什么?每一个option的值是什么?
      • select可以任意起名
      • option的value名称需要与Customer表中的字段名称对应
    • 创建CustomerSimpleSelectServlet完成条件查询
      • 注意SQL语句问题:
      • String sql = “select * from customer where “+sel+” like?”;
    //CustomerSimpleSelectServlet.java
    String sel = request.getParameter("sel");//字段名称
    String msg = request.getParameter("msg");//字段值
    
    //调用service完成查询操作
    CustomerService service = new CustomerService();
    try{
        List<Customer> cs = service.simpleSelect(sel,msg);
    
    }catch(SQLException e){
        e.printStackTrace();
        resp.getWriter().write("条件查询失败");
        return;
    }
    
    
    
    //CustomerService
    public List<Customer> simpleSelect(String sel,String msg){
        return dao.simpleSelect(sel,msg);
    }
    //CustomerDao
    //sel 字段名称
    //msg 字段值
    public List<Customer> simpleSelect(String sel,String msg){
    //SQL语句中,?号会默认加单引号
    //select * from customer where 'name' like '%'小'%'
        //String sql = "select * from customer where ? like '%?%'"
        String sql = "select * from customer where "+sel+" like ?"
        QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource()); 
        return runner.query(sql,new BeanListHandler<Customer>(Customer.class),"%"+msg+"%");
    
    }
    展开全文
  • Dbutils

    2017-08-01 17:01:00
    commons-dbutils 是 Apache 组织提供的一个开源 JDBC工具类库,它是对JDBC的简单封装,学习成本极低,并且使用dbutils能极大简化jdbc编码的工作量,同时也不会影响程序的性能。因此dbutils成为很多不喜欢hibernate的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 9,065
精华内容 3,626
关键字:

dbutils