zoukankan      html  css  js  c++  java
  • BenUtils组件和DbUtils组件

    BenUtils组件和DbUtils组件

    1.BenUtils组件

    1.1.简介

    程序中对javabean的操作很频繁,所有Apache提供了一套开源api,方便javabean的操作!即BeanUtils组件
    BeanUtils组件的作用就是简化javabean的操作

    使用BeanUtils组件

    1. 引入commons-beanutils-1.8.3.jar核心包
    2. 引入日志支持包: commons-logging-1.1.3.jar
      即使用BeanUtils必须导入两个包才可以

    1.2.基本用法,对象属性,对象,map的拷贝

    BeanUtils中有个常用的方法来拷贝数据:
    1.对象属性的拷贝

    BeanUtils.conProperty(admin,"name","jack");
    BeanUtils.setProperty(admin,"psw","123456");
    上面的两个方法作用是一样的,

    2.对象的拷贝

    BeanUtils.copyProperties(newAdmin,admin);

    3.Map数据拷贝到javabean中

    BeanUtils.populate(adminMap,map);
    注意:map中的key要与javabean的属性名称一样

    代码示例:

    
    /**
     * 测试BeanUtils
     * Created by cenyu on 16-12-17.
     */
    public class BeanUtilsDemo {
    
        //1.对javabean的基本操作
        @Test
        public void test1() throws InvocationTargetException, IllegalAccessException {
            //1.基本操作
            Admin admin = new Admin();
    //        admin.setName("jack");
    //        admin.setPsw("123456");
    
            //2.BeanUtils组件实现对象属性的拷贝
            BeanUtils.copyProperty(admin,"name","juerry");
            BeanUtils.copyProperty(admin,"psw","123456");
            //总结1:对于基本数据类型,会自动进行类型转换!
    
            //3.对象的拷贝
            //把admin对象拷贝到一个新的对象。
            Admin newAdmin = new Admin();
            //第一个参数是新对象,第二个参数是要拷贝的对象
            BeanUtils.copyProperties(newAdmin,admin);
    
            //4.map数据,拷贝到对象中
            //定义一个新的Admin对象,此时name和psw的值都是空的
            Admin adminMap = new Admin();
            //创建一个Map对象,并放进去两个值
            Map<String,Object> map = new HashMap<String,Object>();
            map.put("name","Tom");
            map.put("psw","32453");
            //注意:map中的key要与javabean的属性名称一致
            BeanUtils.populate(adminMap,map);
    
            
            //测试
            System.out.println(adminMap.getName());
            System.out.println(admin.getPsw());
        }
    }
    
    

    1.3.日期类的拷贝

    由于表单进来的数据都是String类型,也就是说表单填写一个日期类型,但是在实体要存放的是日期类型,这个时候就要对接收到的数据进行转换格式,常用的转换格式有两种:
    一种是使用自定义方法,重写转换方法
    另外一种是使用BeanUtils提供的日期类型转换工具,但是这种转换工具有一个问题就是可以为null,但是不能为空,为空的化报错
    示例代码如下:

        //2.自定义日期类型转换器
        //需求:从表单接受过来的数据都是字符串,如果中间有时间,就要把字符串转换成日期类型
        @Test
        public void test2() throws InvocationTargetException, IllegalAccessException {
            //模拟表单数据
            String name = "jack";
            String age = "20";
            String birth = "1999-03-24";
    
            //对象
            Admin admin=new Admin();
    
            //注册日期类型转换器
            //1.自定义的方式
    //        ConvertUtils.register(new Converter() {
    //            //转换器的内部实现方法,需要重写
    //            @Override
    //            public Object convert(Class type, Object value) {
    //                //判断
    //                if (type != Date.class){
    //                    return  null;
    //                }
    //                if (value == null || "".equals(value.toString().trim())){
    //                    return null;
    //                }
    //
    //                try {
    //                    //字符串转换为日期
    //                    SimpleDateFormat sdf = new SimpleDateFormat("yyy-MM-dd");
    //                    return sdf.parse(value.toString());
    //                } catch (ParseException e) {
    //                    e.printStackTrace();
    //                    throw new RuntimeException(e);
    //                }
    //            
    //        }, Date.class);
    
            //日期类型转发方式2:
            //使用提供的日期类型转换工具类
            ConvertUtils.register(new DateLocaleConverter(),Date.class);
    
    
            //把表单提交的数据,封装到对象中
            BeanUtils.copyProperty(admin,"name",name);
            BeanUtils.copyProperty(admin,"age",age);
            BeanUtils.copyProperty(admin,"birth",birth);
    
    
            //测试
            System.out.println(admin);
    
        }
    
    ###1.4.封装表单数据到实体
    在servlet中,我们接收jsp传递过来的表单参数,之前的做法是通过request的方法来获取参数值,然后保存早实体对象中,但是这样做是写死的,修改起来会很麻烦,现在将这个过程重新优化封装一下:
    常用的抽象方式有两种,第一种可以使用手写的方法,第一种通过使用BeanUtils工具类,由于两种方法都是抽取出来的抽象方法,所以这个方法是通用的,我们把该方法单独抽取出来,然后在Servlet中调用该方法
    
    用代码分别展示如何在Servlet中接收jsp表单的数据然后封装到实体对象中:
    方法在单独一个类中的封装:
    ```java
    /**
     * 封装从jsp表单中获取参数保存到实体的过程
     * Created by cenyu on 16-12-17.
     */
    
    public class WebUtil {
    
    
        @Deprecated
        public static <T> T copyToBean_old(HttpServletRequest request, Class<T> clazz) {
            try {
                // 创建对象
                T t = clazz.newInstance();
    
                // 获取所有的表单元素的名称
                //getParameterNames();将请求页面中的form表单里所欲具有name属性的表单对象获取,返回一个Enumeration
                Enumeration<String> enums = request.getParameterNames();
                // 遍历
                while (enums.hasMoreElements()) {
                    // 获取表单元素的名称:<input type="password" name="pwd"/>
                    String name = enums.nextElement();  // pwd
                    // 获取名称对应的值
                    String value = request.getParameter(name);
                    // 把指定属性名称对应的值进行拷贝
                    BeanUtils.copyProperty(t, name, value);
                }
    
                return t;
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    
        /**
         * 处理请求数据的封装
         */
        public static <T> T copyToBean(HttpServletRequest request, Class<T> clazz) {
            try {
                // (注册日期类型转换器)
                // 创建对象
                T t = clazz.newInstance();
                BeanUtils.populate(t, request.getParameterMap());
                return t;
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }
    

    调用疯转的结果:
    在Servlet的doGet()方法里面进行方法调用:

    /**
     * 调用jsp表单参数保存到实体对象方法的封装
     * Created by cenyu on 16-12-17.
     */
    public class copyServlet extends javax.servlet.http.HttpServlet {
        protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
            this.doGet(request,response);
        }
        protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
    
            //使用WebUtil组件处理请求数据的封装
            WebUtil.copyToBean(request, Admin.class);
            
            //已经把表单参数封装到实体,可以进行其他操作了
    
        }
    }
    
    

    2.BeanUtils组件优化DAO更新和查询数据库方法

    2.1.对元数据的操作

    此处的元数据是指数据库的定义数据,例如:数据库,表,列的定义信息。使用jdbc来获取这些信息就会使用到元数据
    在jdbc中可以使用:数据元数据,参数元数据,结果集元数据
    常用方法代码:

    /**
     * Created by cenyu on 16-12-17.
     * 测试元数据
     */
    public class metaDataDemo {
        //1.数据库元数据
        @Test
        public void testDB() throws Exception{
            //获取连接
            Connection conn = JdbcUtils.getConnection();
            //创建数据库元数据对象
            DatabaseMetaData metaData=conn.getMetaData();
            //数据库元数据的方法
            //getURL():返回一个String类对象,代表数据库的URL。
            System.out.println(metaData.getURL());
            //getUserName():返回连接当前数据库管理系统的用户名。
            System.out.println(metaData.getUserName());
            //getDatabaseProductName():返回数据库的产品名称。
            System.out.println(metaData.getDatabaseProductName());
        }
    
        //2.参数元数据
        @Test
        public void testParams() throws Exception{
            //获取连接
            Connection conn = JdbcUtils.getConnection();
            //SQL
            String sql = "select * form student where id = ? and name = ?";
            PreparedStatement pstmt = conn.prepareStatement(sql);
            //获取参数元数据
            ParameterMetaData p_metaDate = pstmt.getParameterMetaData();
            //获取参数的个数
            int count = p_metaDate.getParameterCount();
    
            //测试
            System.out.println(count);
        }
    
        //3.结果集元数据
        @Test
        public void testRs() throws Exception{
            String sql = "select * from student";
            //获取连接
            Connection conn = JdbcUtils.getConnection();
            PreparedStatement pstmt = conn.prepareStatement(sql);
            ResultSet rs = pstmt.executeQuery();
            //得到结果集元数据(目标:通过结果集元数据,得到列的名称)
            ResultSetMetaData rs_metaData = rs.getMetaData();
    
            //迭代每一行结果
            while (rs.next()){
                //1.获取列的个数
                int count = rs_metaData.getColumnCount();
                //2.遍历,后去每一列的列名称
                for (int i = 0; i < count ; i++) {
                    //得到列的名称
                    String columnName=rs_metaData.getColumnClassName(i+1);
                    //获取每一行的每一列的值
                    Object columnValue = rs.getObject(columnName);
                    //测试
                    System.out.println(columnName+"="+columnValue);
                }
                System.out.println();
            }
        }
    }
    

    2.2.抽取DAO的更新和查询方法

    在DAO中要经常使用对数据库的更新和查询操作,使用频繁且重复代码跟高,这个时候,我们把DAO中根据对数据库的操作不同,抽取出两个通用方法分别为插入,更改,删除的更新方法update方法和查询的query方法。通用方法接收一个sql语句,一个参数列表,一个操作对象。
    1.现在假设数据库Admin有userName和password这两个字段,实体Admin也只有这个这两个方法,首先,我们在DAO中写出一个BaseDao类用来存放抽取出来的update和query方法
    代码示例如下:

    /**
     * Created by cenyu on 16-12-17.
     * 调用的dao,自己写的所有的dao都继承此类
     * 此类定义了两个通用的方法
     * 1.更新(插入,修改,删除)
     * 2.查询(select语句)
     */
    public class BaseDao {
        //初始化参数
        private Connection conn;
        private PreparedStatement pstmt;
        private ResultSet rs;
    
        //插入,更改,删除通用方法
        public void update(String sql, Object[] patamsValue){
    
    
            try {
                //获取连接
                conn=JdbcUtils.getConnection();
                //创建执行命令的stmt对象
                pstmt=conn.prepareStatement(sql);
                //参数元数据,得到占位符参数的个数
                int count = pstmt.getParameterMetaData().getParameterCount();
                //设置占位符参数的值
                if (patamsValue != null && patamsValue.length>0){
                    //循环给参数赋值
                    for (int i = 0; i < count; i++) {
                        pstmt.setObject(i+1,patamsValue[i]);
                    }
                    //执行更新
                    pstmt.executeUpdate();
                }
            } catch (SQLException e) {
                e.printStackTrace();
                throw new RuntimeException(e);
            }finally {
                JdbcUtils.closeAll(conn,pstmt,null);
            }
        }
    
    
        //查询通用方法
        public <T> List<T> query(String sql,Object[] paramsValue,Class<T> clazz){
    
            try {
                //返回的集合
                List<T> list = new ArrayList<T>();
                //对象
                T t = null;
                //1.获取连接
                conn=JdbcUtils.getConnection();
                //2.创建爱女stmt对象
                pstmt = conn.prepareStatement(sql);
                //3.获取占位符参数的个数,并设置每个参数的值
                int count = pstmt.getParameterMetaData().getParameterCount();
                if (paramsValue != null && paramsValue.length>0){
                    for (int i = 0; i < paramsValue.length; i++) {
                        pstmt.setObject(i+1,paramsValue[i]);
                    }
                }
                //4.执行查询
                rs = pstmt.executeQuery();
                //5.获取结果集元数据
                ResultSetMetaData rsmd = rs.getMetaData();
                //获取列的个数
                int coiumnCount = rsmd.getColumnCount();
                //6.遍历结果集(rs)
                while (rs.next()) {
                    //要封装的对象
                    t = clazz.newInstance();
                    //7.遍历每一行的每一列,封装到数据
                    for (int i = 0; i < coiumnCount ; i++) {
                        //获取每一列的列名称
                        String columnName = rsmd.getColumnName(i+1);
                        //获取每一列的列名称,对应的值
                        Object value = rs.getObject(columnName);
                        //封装,设置到t对象的属性中
                        BeanUtils.copyProperty(t,columnName,value);
                    }
                    //把封装完毕的对象,添加到集合中
                    list.add(t);
                }
                return list;
            }catch (Exception e){
                throw new RuntimeException(e);
            }finally {
                JdbcUtils.closeAll(conn,pstmt,null);
            }
        }
    }
    

    2.通用方法写完之后,我们写具体的DAO方法,通过继承BaseDao类,只需要写参数,然后调用父类中的方法就可以了
    示例代码如下:

    /**
     * Created by cenyu on 16-12-18.
     * 继承BaseDao,实现具体的数据库操作方法
     */
    public class AdminDao extends BaseDao{
    
        //删除
        public void delete(int id){
            String sql = "delete from Admin where id =? ";
            Object[] paramsValue = {id};
            super.update(sql,paramsValue);
        }
        //插入
        public void save(Admin admin){
            String sql = "insert into Admin (userName,password) values (?,?)";
            Object[] paramsValue = {admin.getUserName(),admin.getPassword()};
            super.update(sql,paramsValue);
        }
    
    
        //查询
        public List<Admin> getAll(){
            String sql = "select * from Admin";
            List<Admin> list = super.query(sql,null,Admin.class);
            return list;
        }
    
        //根据条件查询(主键)
        public Admin findById(int id){
            String sql = "select * from admin where id=?";
            List<Admin> list = super.query(sql,new Object[]{id},Admin.class);
            return (list!=null&&list.size()>0) ? list.get(0) : null;
        }
    }
    
    

    3.Dao方法已经写好,这个时候我们可以在其他地方调用Dao里面的方法对数据进行操作了。
    测试类代码如下:

    /**
     * Created by cenyu on 16-12-18.s
     * 测试继承自BaseDao的Dao方法
     */
    public class AdminDaoTest {
    
    
        //测试删除id=8
        @Test
        public void testdelete(){
            AdminDao adminDao = new AdminDao();
            adminDao.delete(6);
        }
    
        //插入测试
        @Test
        public void testInsert(){
            AdminDao adminDao = new AdminDao();
            Admin admin = new Admin();
            admin.setUserName("cenyu");
            admin.setPassword("cenyu");
            adminDao.save(admin);
        }
    
        //测试查询
        @Test
        public void testquery() throws Exception{
            AdminDao adminDao = new AdminDao();
    
            List<Admin> list = adminDao.getAll();
            System.out.println(list);
        }
    }
    
    

    3.DbUtils组件

    3.1.DBUtils组件简介

    commons-dbutils是Apache组织提供的一个开源JDBC工具类库,他是对JDBC的简单封装,学习成本极地,并且使用dbutils能极简化jdbc编码的工作量,同时也不会影响程序的性能
    使用方法:
    引入jar文件:commons-dbutils-1.6.jar

    组件常用API介绍:

    • org.apache.commons.dbutils.QueryRunner
      数据库查询的类库,主要是CURD操作

    • org.apache.commons.dbutils.ResultSetHandler
      处理ResultSet,将查询结果的数据按要求转换为另一种形式
      工具类:
      org.apache.commons.dbutils.DbUtils
      dbutils关闭资源,加载驱动

    3.2.QueryRunner类使用方法

    QueryRunner类简化了SQL的查询工作,与ResultSetHandle组合在一起使用可以完成大部分的数据库操作,能够大大减少编码量
    1.QueryRunner类提供了两个构造方法

    • 默认构造方法
    • 需要一个javax.sql.DataSource来做参数的构造方法

    2.QueryRunner类的主要方法
    public Object query(Connection conn, String sql, Object[] params, ResultSetHandler rsh) :

    执行一个查询操作,在这个查询中,对象数组中的每个元素值被用来作为查询语句的置换参数。该方法会自行处理 PreparedStatement 和 ResultSet 的创建和关闭。

    public Object query(String sql, Object[] params, ResultSetHandler rsh) : 

    几乎与第一种方法一样;唯一的不同在于它不将数据库连接提供给方法,并且它是从提供给构造方法的数据源(DataSource) 或使用的setDataSource 方法中重新获得 Connection。

    public Object query(Connection conn, String sql, ResultSetHandler rsh):

    执行一个不需要置换参数的查询操作。

    public int update(Connection conn, String sql, Object[] params):

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

    public int update(Connection conn, String sql) :

    用来执行一个不需要置换参数的更新操作。

    代码示例:

    /**
     * 使用dbutils组件的QueryRunner类完成CURD,以及批处理
     * Created by cenyu on 16-12-18.
     */
    public class bdutilsUpdate {
        private Connection conn;
    
        //1.删除
        @Test
        public void testDelete() throws SQLException {
            String sql = "delete from Admin where id=?";
            //连接对象
            conn = JdbcUtils.getConnection();
            //创建DBUtils核心工具类对象
            QueryRunner qr=new QueryRunner();
            qr.update(conn,sql,3);//一个参数
            //关闭
            DbUtils.close(conn);
        }
    
        //2.插入
        @Test
        public void testInsert() throws SQLException {
            String sql = "INSERT INTO Admin(userName,password) VALUES (?,?)";
            //连接对象
            conn = JdbcUtils.getConnection();
            //创建DBUtils核心工具类对象
            QueryRunner qr=new QueryRunner();
            qr.update(conn,sql,"a111","a111");//两个参数
            //关闭
            DbUtils.close(conn);
        }
    
    
        //3.更改
        @Test
        public void testUpdate() throws SQLException {
            String sql = "UPDATE Admin SET userName=? WHERE id=?;";
            //连接对象
            conn = JdbcUtils.getConnection();
            //创建DBUtils核心工具类对象
            QueryRunner qr=new QueryRunner();
            qr.update(conn,sql,"Juerry",5);//两个参数
            //关闭
            DbUtils.close(conn);
        }
    
    
        //4.查询
        @Test
        public void testFind() throws SQLException {
            String sql = "select * from Admin where id=?";
            //连接对象
            conn = JdbcUtils.getConnection();
            //创建DBUtils核心工具类对象
            QueryRunner qr=new QueryRunner();
            Admin admin=qr.query(conn,sql,new BeanHandler<Admin>(Admin.class),5);
            //关闭
            System.out.println(admin);
            DbUtils.close(conn);
        }
    
        //5.批处理
        @Test
        public void testBatch() throws SQLException {
            String sql = "insert into Admin (userName, password) values(?,?)";
            conn = JdbcUtils.getConnection();
            QueryRunner qr = new QueryRunner();
            //批量处理
            qr.batch(conn,sql,new Object[][]{{"jack1","888"},{"jack","999"}});
            //关闭
            conn.close();
        }
    }
    

    3.3.ResultSetHandler接口使用方法

    ResultSetHandler接口用于处理java.sql.ResultSet,将数据按要求转换为另一种形式
    ResultSetHandler接口的实现类
    BeanHandler:将结果集中的第一行数据封装到一个对应的JavaBean实例中。
    BeanListHandler:将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List里。
    ArrayHandler:把结果集中的第一行数据转成对象数组。
    ArrayListHandler:把结果集中的每一行数据都转成一个数组,再存放到List中。
    ScalarHandler 查询返回结果记录的第一行的第一列 (在聚合函数统计的时候用)
    MapHandler 查询返回结果的第一条记录封装为map

    代码示例:

    /**
     * 测试ResultSetHandler对查询结构的封装类
     * Created by cenyu on 16-12-18.
     */
    public class bdutilsQuery {
        private Connection conn;
    
        // 一、查询, 自定义结果集封装数据
        @Test
        public void testQuery() throws Exception {
            String sql = "select * from admin where id=?";
            // 获取连接
            conn = JdbcUtils.getConnection();
            // 创建DbUtils核心工具类对象
            QueryRunner qr = new QueryRunner();
            // 查询
            Admin admin = qr.query(conn, sql, new ResultSetHandler<Admin>() {
    
                // 如何封装一个Admin对象
                public Admin handle(ResultSet rs) throws SQLException {
                    if (rs.next()) {
                        Admin admin = new Admin();
                        admin.setUserName(rs.getString("userName"));
                        admin.setPassword(rs.getString("password"));
                        return admin;
                    }
                    return null;
                }
    
            }, 29);
    
            // 测试
            System.out.println(admin);
            // 关闭
            conn.close();
    
        }
    
        // 二、查询, 使用组件提供的结果集对象封装数据
    
        // 1)BeanHandler: 查询返回单个对象
        @Test
        public void testQueryOne() throws Exception {
            String sql = "select * from admin where id=?";
            // 获取连接
            conn = JdbcUtils.getConnection();
            // 创建DbUtils核心工具类对象
            QueryRunner qr = new QueryRunner();
            // 查询返回单个对象
            Admin admin =  qr.query(conn, sql, new BeanHandler<Admin>(Admin.class), 29);
    
            System.out.println(admin);
            conn.close();
        }
    
        // 2)BeanListHandler: 查询返回list集合,集合元素是指定的对象
        @Test
        public void testQueryMany() throws Exception {
            String sql = "select * from admin";
            conn = JdbcUtils.getConnection();
            QueryRunner qr = new QueryRunner();
            // 查询全部数据
            List<Admin> list = qr.query(conn, sql, new BeanListHandler<Admin>(Admin.class));
    
            System.out.println(list);
            conn.close();
        }
        @Test
    //	3) ArrayHandler, 查询返回结果记录的第一行,封装对对象数组, 即返回:Object[]
    //	4) ArrayListHandler, 把查询的每一行都封装为对象数组,再添加到list集合中
    //	5) ScalarHandler 查询返回结果记录的第一行的第一列  (在聚合函数统计的时候用)
    //	6) MapHandler  查询返回结果的第一条记录封装为map
        public void testArray() throws Exception {
            String sql = "select * from admin";
            conn = JdbcUtils.getConnection();
            QueryRunner qr = new QueryRunner();
            // 查询
            //Object[] obj = qr.query(conn, sql, new ArrayHandler());
            //List<Object[]> list = qr.query(conn, sql, new ArrayListHandler());
            //Long num = qr.query(conn, sql, new ScalarHandler<Long>());
            Map<String, Object> map = qr.query(conn,sql, new MapHandler());
    
            conn.close();
        }
    }
    
    

    3.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 commitAndCloseQuietly(Connection conn):

    用来提交连接,然后关闭连接,并且在关闭连接时不抛出SQL异常。

    public static boolean loadDriver(java.lang.String driverClassName):

    这一方装载并注册JDBC驱动程序,如果成功就返回true。使用该方法,你不需要捕捉这个异常ClassNotFoundException。

  • 相关阅读:
    jQuery 基本选择器
    JavaScriptif while for switch流程控制 JS函数 内置对象
    JavaScrip基本语法
    数据库 存储引擎 表的操作 数值类型 时间类型 字符串类型 枚举集合 约束
    数据库基础知识 管理员 用户登录授权的操作
    粘包的产生原理 以及如何解决粘包问题
    socket TCP DPT 网络编程
    2018年年终总结
    Android技术分享
    No accelerator found
  • 原文地址:https://www.cnblogs.com/cenyu/p/6194336.html
Copyright © 2011-2022 走看看