zoukankan      html  css  js  c++  java
  • JDBC(7)—DAO

    1. 介绍:
      DAO(Data Access Object):数据访问对象

      • 1.what:访问数据信息的类,包含了对数据的CRUD(create read、update、delete),而不包含业务相关的信息。
        2.why:实现功能模块化,更有利于代码的维护和升级。
      • 3.how:使用JDBC编写DAO可能会包含的方法。
      • public void update(String sql, Object … objects)
      • public T get(Class clazz, String sql, Object … objects)
      • public List getForList(Class calzz, String sql, Object … objects)
      • public E getForValue(String sql, Object … objects)

      • 版本:1.0,之后还会对DAO进行修改,这只是一个非常简单的介绍。

    2.实例:

    DAO层代码
    public class DAO1_7 {
    
        /**
         * 1.更新操作,insert、update、delete操作都包含在其中。
         * @param sql
         * @param objects
         */
        public void update(String sql, Object ...objects){
            Connection conn = null;
            PreparedStatement preparedstatement = null;
            try {
                conn = TestTools.getConnection();
                preparedstatement = conn.prepareStatement(sql);
                for(int i = 0; i < objects.length; i++){
                    preparedstatement.setObject(i + 1, objects[i]);
                }
                preparedstatement.executeUpdate();
            } catch (Exception e) {
                e.printStackTrace();
            }finally{
                TestTools.release(preparedstatement, conn);
            }
        }
        /**
         * 2.查询一条记录,返回对应的对象。
         * @param clazz
         * @param sql
         * @param objects:占位符从1开始
         * @return
         */
        public <T> T get(Class<T> clazz,String sql,Object ...objects){
            T entity = null;
            Connection conn = null;
            PreparedStatement preparedstatement = null;
            ResultSet rs = null;
            ResultSetMetaData rsmd = null;
            try {
                //1.获取Connection
                conn = TestTools.getConnection();
                //2.获取PreparedStatement
                preparedstatement = conn.prepareStatement(sql);
                //3.填充占位符
                for(int i = 0; i < objects.length; i++){
                    preparedstatement.setObject(i + 1, objects[i]);
                }
                //4.进行查询,获取ResultSet对象
                rs = preparedstatement.executeQuery();
                //5.若ResultSet中有数据,准备一个Map<String,Object>:键:存放列的别名,值:存放列的值
                if(rs.next()){
                    Map<String,Object> values = new HashMap<String,Object>();   
                    //6.得到ResultSetMetaData对象。
                    rsmd = rs.getMetaData();
                    //7.处理ResultSet,把指针向下移动一个单位。(在判断是否有数据是已经移动,此处不在需要)
    
                    //8.ResultSetMetaData对象中得到结果集中有多少列
                    int columnCount = rsmd.getColumnCount();
                    //9.由ResultSetMetaData得到每一列的值,再由ResultSet得到具体每一列的值
                    for(int i = 0; i < columnCount; i++){
                        String columnLabel = rsmd.getColumnLabel(i + 1);
                        Object columnValue = rs.getObject(i + 1);
                        //10.填充Map对象
                        values.put(columnLabel, columnValue);
                    }
                    //11.使用反射创建Class对应的对象
                    entity = clazz.newInstance();
                    //12.遍历Map对象,使用反射遍历填充对象的属性值,Map:key为属性名,value为属性值
                    for(Map.Entry<String, Object> entry : values.entrySet()){
                        String propertyName = entry.getKey();
                        Object value = entry.getValue();
    
                        TestTools.setFieldValue(entity, propertyName, value);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }finally{
                TestTools.release(rs, preparedstatement, conn);
            }
            return entity;
        }
        /**
         * 3.查询多条记录,返回对应的对象的集合。
         * @param calzz
         * @param sql
         * @param objects
         * @return
         */
        public <T> List<T> getForList(Class<T> calzz,String sql,Object ... args){
            List<T> list = new ArrayList<>();//用于返回多个对象
            Connection conn = null;
            PreparedStatement preparedstatement = null;
            ResultSet rs = null;
            try {
                //1.获取Connection连接
                conn = TestTools.getConnection();
                //2.获取PreparedStatement对象
                preparedstatement = conn.prepareStatement(sql);
                //3.填充占位符
                for(int i = 0; i < args.length; i++){
                    preparedstatement.setObject(i + 1, args[i]);
                }
                //4.进行查询,获取ResultSet对象
                rs = preparedstatement.executeQuery();
                //5.若ResultSet中有数据,准备一个List<Map<String,Object>>:
                //键:存放列的别名,值:存放列的值,其中一个Map对象对应一条记录,values用于存放
                List<Map<String, Object>> values = new ArrayList<>();
                Map<String, Object> map = null;
                //6.得到ResultSetMetaData对象。
                ResultSetMetaData rsmd = preparedstatement.getMetaData();
                //7.处理ResultSet,使用while()循环。(在判断是否有数据是已经移动,此处不在需要)
                while(rs.next()){
                    map = new HashMap<>();
                    //8.把每个列别名和列值取出来,存到Map对象中
                    for(int i = 0; i < rsmd.getColumnCount(); i++){
                        String columnName = rsmd.getColumnLabel(i + 1);
                        Object columnValue = rs.getObject(i + 1);
    
                        map.put(columnName, columnValue);
                    }
                    //9.再把Map对象存到List中
                    values.add(map);
    
                }
                //12.判断List是否为空集合,若不空则便利List得到一个个Map对象,
                //再把Map对象转化成Class参数对应的Object对象
                T bean = null;
                if(values.size() > 0){
                    for(Map<String, Object> m : values){
                        bean = calzz.newInstance();
                        for(Map.Entry<String, Object> entry : m.entrySet()){
                            String propertyName = entry.getKey();
                            Object propertyValue = entry.getValue();
                            //为类成员变量赋值。
                            TestTools.setFieldValue(bean, propertyName, propertyValue);
                        }
                        //13.把Object对象放入到list中
                        list.add(bean);
                    }
                }
    
            } catch (Exception e) {
                e.printStackTrace();
            }finally{
                TestTools.release(rs, preparedstatement, conn);
            }
    
            return list;
        }
        /**
         * 4_1.功能:查询多条记录,返回对应的对象的集合。对以上3.方法进行的拆分。
         *与上一致,其中对ResultSet对象之后的代码进行优化,包括每次循环都都要获取列别名进行优化修改。
         * @param calzz
         * @param sql
         * @param objects
         * @return
         */
        public <T> List<T> getForLists(Class<T> calzz,String sql,Object ... args){
            List<T> list = new ArrayList<>();//用于接收返回的多个对象
            Connection conn = null;
            PreparedStatement preparedstatement = null;
            ResultSet rs = null;
            try {
                //1.得到结果集
                conn = TestTools.getConnection();
                preparedstatement = conn.prepareStatement(sql);
                for(int i = 0; i < args.length; i++){
                    preparedstatement.setObject(i + 1, args[i]);
                }
                rs = preparedstatement.executeQuery();
                //-----------------修改
                //2.处理结果集,得到Map的List,其中一个Map对象就是一条记录,Map中Key表示列别名,Value表示列值
                List<Map<String, Object>> values = handleResultSetToMapList(rs);
                //3.把Map的list转为Clazz对应的list,其中Map的Key表示Class的成员属性,Value表示成员属性的值
                list = transfterMapListToBeanList(calzz, values);
    
            } catch (Exception e) {
                e.printStackTrace();
            }finally{
                TestTools.release(rs, preparedstatement, conn);
            }
            return list;
        }
    
        /**
         * 4_2.处理结果集,获取Map的List,其中一条Map对象对应一条记录。
         * @param rs
         * @return
         * @throws SQLException
         */
        private List<Map<String, Object>> handleResultSetToMapList(ResultSet rs)
                throws SQLException {
            List<Map<String, Object>> values = new ArrayList<>();
            Map<String, Object> map = null;
            //---------------此处被修改。6.得到ResultSetMetaData对象。
            List<String> columnLabels = getColumnLabels(rs);
            while(rs.next()){
                map = new HashMap<>();
                //---------------此处被修改。8.把每个列别名和列值取出来,存到Map对象中
                for(String columnName : columnLabels){
                    Object columnValue = rs.getObject(columnName);
                    map.put(columnName, columnValue);
                }
                values.add(map);
            }
            return values;
        }
        /**
         * 4_3获取结果集所有的列别名,存到集合中,再返回集合。
         * @param rs
         * @return
         */
        private List<String> getColumnLabels(ResultSet rs){
            List<String> labels = new ArrayList<>();
            try {
                ResultSetMetaData rsmd = rs.getMetaData();
                for(int i = 0; i < rsmd.getColumnCount(); i++){
                    labels.add(rsmd.getColumnLabel(i + 1));
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
    
            return labels;
        }
        /**
         * 4_4.
         * @param calzz
         * @param values
         * @return
         * @throws InstantiationException
         * @throws IllegalAccessException
         */
        private <T> List<T> transfterMapListToBeanList(Class<T> calzz,
                List<Map<String, Object>> values) throws InstantiationException,
                IllegalAccessException {
            List<T> result = new ArrayList<>();
            T bean = null;
            if(values.size() > 0){
                for(Map<String, Object> m : values){
                    bean = calzz.newInstance();
                    for(Map.Entry<String, Object> entry : m.entrySet()){
                        String propertyName = entry.getKey();
                        Object propertyValue = entry.getValue();
                        //为类成员变量赋值。
                        TestTools.setFieldValue(bean, propertyName, propertyValue);
                    }
                    //13.把Object对象放入到list中
                    result.add(bean);
                }
            }
            return result;
        }
        /**
         * 返回某条记录的某一个字段的值或一个统计的值(一共有多少条记录等。),即:确定的某一行的某个字段的值,或者计算的值
         * @param sql
         * @param objects
         * @return
         */
        public <E> E getForValue(String sql, Object ... objects){
            Connection conn = null;
            PreparedStatement ps = null;
            ResultSet rs = null;
            try {
                //1.得到结果集:该结果集应该只有一行,且只有一列
                conn = TestTools.getConnection();
                ps = conn.prepareStatement(sql);
                for(int i = 0; i < objects.length; i++){
                    ps.setObject(i + 1, objects[i]);
                }
                rs = ps.executeQuery();
                if(rs.next()){
                    //2.取得结果
                    return (E) rs.getObject(1);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }finally{
                TestTools.release(rs, ps, conn);
            }
            return null;
        }
    }
    
    测试dao层代码
    public class DAOTest_1_7 {
    
        DAO1_7 dao = new DAO1_7();
        //测试:DAO——update(String sql, Object ...objects)方法。
        @Test
        public void testUpdate() {
            String sql = "insert into customers(name,age,birth,address) " +
                    "value(?,?,?,?)";
            dao.update(sql, "刘飒","20",new Date(new java.util.Date().getTime()),"河南省");
        }
    
        //测试:DAO——get(Class<T> clazz,String sql,Object ...objects)方法。
        @Test
        public void testGet() {
            String sql = "select * from customers where id = ?";
            Customers customers = dao.get(Customers.class, sql, 12);
            System.out.println(customers);
        }
    
        //测试:DAO——getForList(Class<T> calzz,String sql,Object ... args)方法。
        @Test
        public void testGetForList() {
            String sql = "select FlowID ,Type , IDCard , ExamCard " +
        ", StudentName , Location , Grade  from examStudent";
            List<Student> student = dao.getForLists(Student.class, sql);
            for(int i = 0; i < student.size(); i++){
                System.out.println(student.get(i));
            }
        }
    
        //测试:DAO——getForValue(String sql, Object ... objects)
        @Test
        public void testGetForValue(){
            String sql = "select examCard from examstudent where FlowID = ?";
            String examCard = dao.getForValue(sql, 33);
            if(examCard == null){
                System.out.println("查无信息!");
            }else{
                System.out.println(examCard);
            }
            sql = "select Count(*) from examstudent";
            Object count = dao.getForValue(sql);
            System.out.println("共有:"+count+"行");
        }
    }
    
  • 相关阅读:
    基于Metronic的Bootstrap开发框架经验总结(14)--条码和二维码的生成及打印处理
    基于Metronic的Bootstrap开发框架经验总结(13)--页面链接收藏夹功能的实现2(利用Sortable进行拖动排序)
    基于Metronic的Bootstrap开发框架经验总结(12)--页面链接收藏夹功能的实现
    C#开发微信门户及应用(45)--微信扫码登录
    从博客园迁移到简书平台
    基于MVC4+EasyUI的Web开发框架经验总结(17)--布局和对话框自动适应大小的处理
    基于Metronic的Bootstrap开发框架经验总结(11)--页面菜单的几种呈现方式
    基于MVC4+EasyUI的Web开发框架经验总结(16)--使用云打印控件C-Lodop打印页面或套打报关运单信息
    在Winform程序中设置管理员权限及为用户组添加写入权限
    C#开发微信门户及应用(44)--微信H5页面开发的经验总结
  • 原文地址:https://www.cnblogs.com/tengpengfei/p/10454015.html
Copyright © 2011-2022 走看看