DBUtils和Spring Jdbc Template

DBUtils和Spring Jdbc Template

  • Dbutils
    • DBUtils简介
    • DbUtils类
    • QueryRunner类
    • ResultSetHandler接口
    • 开发步骤
  • Jdbc Template
    • JdbcTemplate简介
    • JdbcTemplate主要提供以下四类方法
    • JdbcTemplate的开发步骤

Dbutils

DBUtils简介

  • commons-dbutils 是 Apache 组织提供的一个开源 JDBC工具类库,它是对JDBC的简单封装,学习成本极低,并且使用dbutils能极大简化jdbc编码的工作量,创建连接、结果集封装、释放资源,同时也不会影响程序的性能。创建连接、结果集封装、释放资源因此dbutils成为很多不喜欢hibernate的公司的首选。

  • API介绍:

    • org.apache.commons.dbutils.QueryRunner — 核心类。执行SQL查询以处理结果集。这个类是线程安全的。

    • org.apache.commons.dbutils.ResultSetHandler — 结果集封装器

    • org.apache.commons.dbutils.DbUtils — 工具类

  • 学习地址及jar包下载:http://commons.apache.org/proper/commons-dbutils/download_dbutils.cgi

    连接数据库jar包mysql-connector-java-5.1.47:https://dev.mysql.com/downloads/connector/j/

  • 本文是使用的数据库连接池是上一篇使用的C3P0文章链接:https://blog.csdn.net/SYJ_1835_NGE/article/details/88694434

DbUtils类

DbUtils:提供如加载驱动、关闭连接、事务提交、回滚等常规工作的工具类,里面的所有方法都是静态的。主要方法如下:

  • DbUtils类提供了三个重载的关闭方法close() 。这些方法检查所提供的参数是不是NULL,如果不是的话,它们就关闭Connection、Statement和ResultSet。

        public static void close(Connection conn)	throws SQLException
        public static void close(ResultSet rs)    	throws SQLException
        public static void close(Statement stmt)    throws SQLException
    
  • 这一类"quietly"方法不仅能在Connection、Statement和ResultSet为NULL情况下避免关闭,还能隐藏一些在程序中抛出的SQLException。

        public static void closeQuietly(Connection conn,Statement stmt, ResultSet rs)
        public static void closeQuietly(Connection conn)
        public static void closeQuietly(ResultSet rs)
        public static void closeQuietly(Statement stmt)
    
  • 用来提交连接,然后关闭连接,并且在关闭连接时不抛出SQL异常。

        static void	commitAndClose(Connection conn)
        static void	commitAndCloseQuietly(Connection conn)
    
  • 装载并注册JDBC驱动程序,如果成功就返回true。使用该方法,你不需要捕捉这个异常ClassNotFoundException。

        static boolean	loadDriver(ClassLoader classLoader, String driverClassName)
        static boolean	loadDriver(String driverClassName)
    
  • 用于事务的回滚并且在资源使用完后将连接关闭

        static void	rollback(Connection conn)
        static void	rollbackAndClose(Connection conn)
        static void	rollbackAndCloseQuietly(Connection conn)
    

QueryRunner类

注意:

	1、如果使用 QueryRunner(DataSource ds) 构造器创建QueryRunner对象,需要使用连接池,如DBCP、C3P0等等,数据库事务交给DBUtils框架进行管理 ---- 默认情况下每条SQL语句单独一个事务。
	2、如果使用 QueryRunner() 构造器创建QueryRunner对象 ,需要自己管理事务,因为框架没有连接池无法获得数据库连接。
  • 该类简单化了SQL查询,它与ResultSetHandler组合在一起使用可以完成大部分的数据库操作,能够大大减少编码量。

  • QueryRunner类提供了两个比较常使用的构造方法:

    • 默认的构造方法(无参的构造函数):在执行查询操作的时候需要手动传入Connection对象

          public QueryRunner()
      
    • 需要一个 javax.sql.DataSource 来作参数的构造方法:

          public QueryRunner(DataSource ds)
      
    • 使用数据库连接池来获取数据源,C3P0、DBCP或者Durid

          public static DataSource getDataSource() {
                  return ds;
              }
      
  • 常用方法:

    • 批处理

          batch(Connection conn, String sql, Object[][] params)  // 传递连接批处理
          batch(String sql, Object[][] params)  // 不传递连接批处理
      
    • 更新操作

      	//无参构造函数需要手动传入连接对象
          int	update(Connection conn, String sql)
          int	update(Connection conn, String sql, Object... params)
          int	update(Connection conn, String sql, Object param)
           //有参的构造函数(传入数据源的)Object... params和参数注入的 ?一 一对应
          int	update(String sql)
          int	update(String sql, Object... params)
          int	update(String sql, Object param)    
      
    • 查询操作

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

ResultSetHandler接口

  • 该接口用于处理 java.sql.ResultSet,将数据库的记录按要求转换为另一种形式。(List、Map、Bean等)

  • ResultSetHandler 接口提供了一个单独的方法:

        //将参数中的结果集ResultSet rs转化为另外一种形式
        T handle(ResultSet rs)  throws SQLException
    
  • ResultSetHandler 接口的实现类(构造方法不唯一,在这里只用最常见的构造方法):

    • **BeanHandler(Class type):**将结果集中的第一行数据封装到一个对应的JavaBean实例中。也可以指定参数返回指定参数所在行的数据,下面有例子进行展示

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

    • **ArrayHandler():**把结果集中的第一行数据转成对象数组(存入Object[])。

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

    • **ScalarHandler(int columnIndex) || ScalarHandler(String columnIndex):**通常用来保存只有一行一列的结果集。通常用来执行聚合函数

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

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

    • **BeanMapHandler(Class type):**将结果集每一条数据,转为JavaBean对象,再保存到map集合中

          BeanMapHandler(Class<V> type)
          BeanMapHandler(Class<V> type, int columnIndex)
          BeanMapHandler(Class<V> type, RowProcessor convert)
          BeanMapHandler(Class<V> type, String columnName)
      
    • **KeyedHandler(String columnName):**将结果集每一行数据保存到一个“小”map中,key为列名,value该列的值,再将所有“小”map对象保存到一个“大”map中 , “大”map中的key为指定列,value为“小”map对象

         	KeyedHandler(
          KeyedHandler(int columnIndex)
          KeyedHandler(RowProcessor convert)
          KeyedHandler(String columnName)
      

开发步骤

  1. 创建mydb数据库和employee表

    CREATE TABLE `employee` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `username` varchar(20) DEFAULT NULL,
      `salary` int(12) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8
    --------------------- 
    作者:SYJ_追梦逐星 
    来源:CSDN 
    原文:https://blog.csdn.net/SYJ_1835_NGE/article/details/88694434 
    版权声明:本文为博主原创文章,转载请附上博文链接!
    
  2. 导入相关jar包 commons-dbutils-1.7.jar

  3. 创建QueryRunner对象。依赖于数据源DataSource

        //数据源可以通过C3P0、DBCP或者Druid获取
        QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());
    
  4. 调用QueryRunner的方法来完成CRUD的操作

    • update(String sql, Object… params):执行DML语句。增、删、改语句。
    • query(String sql, ResultSetHandler rsh, Object… params):执行查询语句,将其封装成不同的数据方式。
  5. 对于CUD,执行DML语句。增、删、改语句。

    public class Demo1 {
        //如果使用 QueryRunner(DataSource ds) 构造器创建QueryRunner对象,需要使用连接池,
        // 如DBCP、C3P0等等,数据库事务交给DBUtils框架进行管理 ---- 默认情况下每条SQL语句单独一个事务。
        //如果使用 QueryRunner() 构造器创建QueryRunner对象 ,需要自己管理事务,因为框架没有连接池无法获得数据库连接。
        @Test
        //快速感受DBUtils之插入操作
        public void test1() {
            String sql = "insert into employee (username,salary) values (?,?)";
            QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());
            try {
                int count = queryRunner.update(sql, "蜘蛛精", "1000");
                if (count > 0) {
                    System.out.println("插入成功");
                } else {
                    System.out.println("插入失败");
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    
        @Test
        //快速感受DBUtils之更新操作
        public void test2() {
            String sql = "update employee set username=? where id=?";
            QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());
            try {
                int count = queryRunner.update(sql, "蛇精", 12);
                if (count > 0) {
                    System.out.println("更新成功");
                } else {
                    System.out.println("更新失败");
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    
        @Test
        //快速感受DBUtils之删除操作
        public void test3() {
            String sql = "delete from employee where username=?";
            QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());
            try {
                int count = queryRunner.update(sql, "蛇精");
                if (count > 0) {
                    System.out.println("刪除成功");
                } else {
                    System.out.println("刪除失败");
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    // 对于R,需要用到ResultSetHandler接口,该接口有9大实现类
    }
    
  6. 执行查询语句,将其封装成不同的数据方式。

    • 编写接口
        public interface employeeDao {
            /**
             實現DBUtils的CRUD
             包含九种不同类型的查询结果的封装
             */
            //CUD操作
            public  void add()throws SQLException;
            public  void update()throws SQLException;
            public  void delete()throws SQLException;
            //简单的查询操作
            //对结果集的封装
            public  employee findById(int id)throws SQLException;
            public List<employee> findAll()throws SQLException;
            public  Long findCount()throws SQLException;
            public  String findArrayHandler()throws SQLException;
            public  List<Object[]> findArrayListHandler()throws SQLException;
            public Map<Integer, employee> findBeanMapHandler()throws SQLException;
            public   Map<Object, Map<String, Object>> findKeyedHandler(int  id )throws 		SQLException;
            public  Map<String, Object>  findMapHandler()throws SQLException;
            public  List<Map<String, Object>> findMapListHandler()throws SQLException;
        }
    
    
    • 实现接口
    public class employeeDaoImpl implements employeeDao {
        QueryRunner runner = null;
    
        public employeeDaoImpl() {
            runner = new QueryRunner(C3P0Utils.getDataSource());
        }
    
        @Test
        //添加一条employee
        @Override
        public void add() throws SQLException {
            String sql = "insert into employee (username , salary) values (?,?) ";
            int count = runner.update(sql, "太上老君", 12000);
            if (count > 0) {
                System.out.println("添加成功");
            } else {
                System.out.println("添加失败");
            }
        }
    
        @Test
        //更新employee
        @Override
        public void update() throws SQLException {
            String sql = "update employee set username=? where id=?";
            int count = runner.update(sql, "牛魔王", 11);
            if (count > 0) {
                System.out.println("更新成功");
            } else {
                System.out.println("更新失败");
            }
        }
    
        @Test
        //删除employee
        @Override
        public void delete() throws SQLException {
            String sql = "delete from employee where username=?";
            int count = runner.update(sql, "牛魔王");
            if (count > 0) {
                System.out.println("刪除成功");
            } else {
                System.out.println("刪除失败");
            }
    
        }
    
        /**
         * BeanHandler
         * BeanListHandler
         * ScalarHandler
         * ArrayHandler
         * ArrayListHandler
         * MapHandler
         * MapListHandler
         * BeanMapHandler
         * KeyedHandler
         */
        //  BeanHandler 过id查找employee(结果集BeanHandler)
        @Override
        public employee findById(int id) throws SQLException {
            String sql = "select * from employee where id =?";
            employee e = runner.query(sql, new BeanHandler<employee>(employee.class), id);
            System.out.println(e);
            return e;
        }
    
        //  BeanListHandler 查找所有employee(结果集BeanListHandler)
        @Override
        public List<employee> findAll() throws SQLException {
            String sql = "select * from employee ";
            List<employee> list = runner.query(sql, new BeanListHandler<employee>(employee.class));
            return list;
        }
    
        //  ScalarHandler 查找employee的总数(结果集ScalarHandler)
        @Override
        public Long findCount() throws SQLException {
            String sql = "select count(id) from employee ";
            Long count = runner.query(sql, new ScalarHandler<Long>());
            return count;
        }
    
        @Override
        //  ArrayHandler   将结果集第一行数据保存到Object[]中(结果集ArrayHandler)
        public String findArrayHandler() throws SQLException {
            String sql = "select * from employee";
            Object[] obj = runner.query(sql, new ArrayHandler());
            return Arrays.toString(obj);
        }
    
        @Override
        //   ArrayListHandler 将结果集每一条数据,转为Object[],再保存到list集合中(结果集ArrayListHandler)
        public List<Object[]> findArrayListHandler() throws SQLException {
            String sql = "select * from employee";
            List<Object[]> list = runner.query(sql, new ArrayListHandler());
            return list;
        }
    
        @Override
        // BeanMapHandler  将结果集每一条数据,转为JavaBean对象,再保存到map集合中(结果集BeanMapHandler)
        public Map<Integer, employee> findBeanMapHandler() throws SQLException {
            String sql = "select * from employee";
            Map<Integer, employee> map = runner.query(sql, new BeanMapHandler<>(employee.class));
            return map;
        }
    
        @Override
        //   KeyedHandler  将结果集每一行数据保存到一个“小”map中,key为列名,value该列的值,再将所有“小”map对象保存到一个“大”map中
        //  “大”map中的key为指定列,value为“小”map对象(结果集KeyedHandler)
        public Map<Object, Map<String, Object>> findKeyedHandler(int id) throws SQLException {
            String sql = "select * from employee";
            Map<Object, Map<String, Object>> maps = runner.query(sql, new KeyedHandler<>(id));
            return maps;
        }
    
        @Override
        //  MapHandler  将结果集第一行数据封装到Map集合中,key是列名,value为该列的值(结果集MapHandler)
        public Map<String, Object> findMapHandler() throws SQLException {
            String sql = "select * from employee";
            Map<String, Object> map = runner.query(sql, new MapHandler());
            return map;
        }
    
        @Override
        // MapListHandler  将结果集每一行数据保存到map中,key列名 value该列的值 ---- 再将所有map对象保存到List集合中
        //(结果集MapListHandler)
        public List<Map<String, Object>> findMapListHandler() throws SQLException {
            String sql = "select * from employee";
            List<Map<String, Object>> lists = runner.query(sql, new MapListHandler());
            return lists;
        }
    }
    
    • 测试类
    public class Mian {
        public static void main(String[] args) throws SQLException {
            employeeDaoImpl emi = new employeeDaoImpl();
            //BeanHandler类
            // emi.findById(1);
    
            //BeanListHandler类
            //List list = emi.findAll();
            //System.out.println(list);
    
            //ScalarHandler类
            //Long count = emi.findCount();
            //System.out.println(count);
    
            //ArrayHandler类
            //String str = emi.findArrayHandler();
            //System.out.println(str);
    
            //ArrayListHandler类
            //List list = emi.findArrayListHandler();
            //for (Object[] objects : list) {
            //System.out.println(Arrays.toString(objects));
            //}
    
            //BeanMapHandler类
            //Map map = emi.findBeanMapHandler();
            //for (Integer integer : map.keySet()) {
            //System.out.println(map.get(integer));
            //}
    
            //KeyedHandler类
            //Map> map = emi.findKeyedHandler(1);
            //for (Object o : map.keySet()) {
            //Map map1 = map.get(o);
            //for (String s : map1.keySet()) {
            //System.out.print(s + "=" + map1.get(s)+"\t");
            //}
            //System.out.println();
            // }
    
            //MapHandler类
            //Map map = emi.findMapHandler();
            //System.out.println(map);
    
            //MapListHandler类
            List> lists = emi.findMapListHandler();
            for (Map map : lists) {
                for (String s : map.keySet()) {
                    System.out.print(s + "=" + map.get(s) + "\t");
                }
                System.out.println();
            }
        }
    }
    
    

Jdbc Template

JdbcTemplate简介

  • Spring框架对JDBC的简单封装。提供了一个JDBCTemplate对象简化JDBC的开发
  • Spring对数据库的操作在jdbc上面做了深层次的封装,使用spring的注入功能,可以把DataSource注册到JdbcTemplate之中。
  • JdbcTemplate位于spring-jdbc-5.0.0.RELEASE.jar中。其全限定命名为org.springframework.jdbc.core.JdbcTemplate。要使用JdbcTemlate还需一个这个包spring-tx-5.0.0.RELEASE.jar包含了一下事务和异常控制。
  • 不要忘记导入数据库的连接jar包

JdbcTemplate主要提供以下四类方法

  • execute方法:可以用于执行任何SQL语句,一般用于执行DDL语句;
  • update方法及batchUpdate方法:update方法用于执行新增、修改、删除等语句;batchUpdate方法用于执行批处理相关语句;
  • query方法及queryForXXX方法:用于执行查询相关语句;
  • call方法:用于执行存储过程、函数相关语句。

JdbcTemplate的开发步骤

  1. 导入相应jar包。

  2. 创建JdbcTemplate对象。依赖于数据源DataSource

    Druid的相关介绍:https://blog.csdn.net/SYJ_1835_NGE/article/details/88694434

         //DruidUtils是Druid数据库连接池抽取的工具类
    	 //传入数据源
         JdbcTemplate template = new JdbcTemplate(DruidUtils.getDataSource());
    
  3. 调用JdbcTemplate的方法来完成CRUD的操作

    • update():执行DML语句。增、删、改语句

    • queryForMap():查询结果将结果集封装为map集合,将列名作为key,将值作为value 将这条记录封装为一个map集合

      • 注意:这个方法查询的结果集长度只能是1
    • queryForList():查询结果将结果集封装为list集合

      • 注意:将每一条记录封装为一个Map集合,再将Map集合装载到List集合中
    • query():查询结果,将结果封装为JavaBean对象

      • query的参数:RowMapper

      • 一般我们使用BeanPropertyRowMapper实现类。可以完成数据到JavaBean的自动封装

      • new BeanPropertyRowMapper<类型>(类型.class)

      • List<User> list= template.query(sql, new BeanPropertyRowMapper<User>(User.class));
        
    • queryForObject:查询结果,将结果封装为对象

      • 一般用于聚合函数的查询
  4. 创建一个mydb数据库和一个user表:

     user  | CREATE TABLE `user` (
      `id` int(10) NOT NULL AUTO_INCREMENT,
      `username` varchar(255) DEFAULT NULL,
      `password` varchar(20) DEFAULT NULL,
      `score` double(4,2) DEFAULT NULL,
      `address` varchar(255) DEFAULT NULL,
      `brith` date DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8
    
  5. 编写User实体类

    public class User {
    
        Integer id;
        String username;
        String password;
        Double score;
        String address;
        Date brith;
    
        public Integer getId() {
            return id;
        }
        public void setId(Integer id) {
            this.id = id;
        }
        public String getUsername() {
            return username;
        }
        public void setUsername(String username) {
            this.username = username;
        }
        public String getPassword() {
            return password;
        }
        public void setPassword(String password) {
            this.password = password;
        }
        public Double getScore() {
            return score;
        }
        public void setScore(Double score) {
            this.score = score;
        }
        public String getAddress() {
            return address;
        }
        public void setAddress(String address) {
            this.address = address;
        }
        public Date getBrith() {
            return brith;
        }
        public void setBrith(Date brith) {
            this.brith = brith;
        }
        @Override
        public String toString() {
            return "User{" +
                    "id=" + id +
                    ", username='" + username + '\'' +
                    ", password='" + password + '\'' +
                    ", score=" + score +
                    ", address='" + address + '\'' +
                    ", brith=" + brith +
                    '}';
        }
    }
    
  6. 执行增删改操作

    public class Test1 {
    
        private JdbcTemplate template = new JdbcTemplate(DruidUtils.getDataSource());
    
        //1、修改id为1的score为10000
        @Test
        public void test1() {
            String sql = "update user set score=? where id=?";
            int count = template.update(sql, 88.88, 1);
            if (count > 0) {
                System.out.println("更新数据成功!!!");
            } else {
                System.out.println("更新数据失败!!!");
            }
        }
    
        //2、添加一条记录
        @Test
        public void test2() {
            String sql = "insert into user values (?,?,?,?,?,?)";
            int count = template.update(sql, null, "孙悟空", "222222", "63.36", "广东", "1996-06-11");
            if (count > 0) {
                System.out.println("插入数据成功!!!");
            } else {
                System.out.println("插入数据失败!!!");
            }
        }
    
        //3、删除一条记录
        @Test
        public void test3() {
            String sql = "delete from user  where id=?";
            int count = template.update(sql, 8);
            if (count > 0) {
                System.out.println("删除数据成功!!!");
            } else {
                System.out.println("删除数据失败!!!");
            }
        }
    }
    
  7. 执行查询语句

    /**
     * Spring JdbcTempalte的练习
     */
    public class Test1 {
    
        private JdbcTemplate template = new JdbcTemplate(DruidUtils.getDataSource());
    
        //4、查询数据库为一将其封装成Map集合
        @Test
        public void test4() {
            String sql = "select * from user where id=?";
            Map<String, Object> map = template.queryForMap(sql, 1);
            System.out.println(map);
        }
    
        //5、查询数据库所有记录将其封装成List
        @Test
        public void test5() {
            String sql = "select * from user ";
            List<Map<String, Object>> list = template.queryForList(sql);
            for (Map<String, Object> map : list) {
                System.out.println(map);
            }
        }
    
        //6.1、查询数据库所有记录将其封装成指定的对象
        @Test
        public void test6() {
            String sql = "select * from user ";
    
           List<User> list= template.query(sql, new RowMapper<User>() {
                @Override
                public User mapRow(ResultSet rs, int i) throws SQLException {
                    User user = new User();
                    int id = rs.getInt("id");
                    String username = rs.getString("username");
                    String password = rs.getString("password");
                    double score = rs.getDouble("score");
                    String address = rs.getString("address");
                    Date brith = rs.getDate("brith");
    
                    user.setId(id);
                    user.setUsername(username);
                    user.setPassword(password);
                    user.setScore(score);
                    user.setAddress(address);
                    user.setBrith(brith);
                    return user;
                }
            });
            for (User user : list) {
                System.out.println(user);
            }
        }
        //6.2、查询数据库所有记录将其封装成指定的对象
        @Test
        public void test6_1() {
            String sql = "select * from user ";
    		//	星标重点
            List<User> list= template.query(sql, new BeanPropertyRowMapper<User>(User.class));
            for (User user : list) {
                System.out.println(user);
            }
        }
        //7、查询数据库所有记录的数量
        @Test
        public void test7() {
            String sql = "select count(id) from user ";
            Long counts = template.queryForObject(sql, Long.class);
            System.out.println(counts);
        }
    }
    

你可能感兴趣的:(JavaWeb)