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+"行");
        }
    }
    
  • 相关阅读:
    CODING x 百果园 _ 水果零售龙头迈出 DevOps 体系建设第一步
    Nocalhost 亮相 CD Foundation 国内首届 Meetup,Keith Chan 将出席致辞
    做云原生时代标准化工具,实现高效云上研发工作流
    打造数字化软件工厂 —— 一站式 DevOps 平台全景解读
    WePack —— 助力企业渐进式 DevOps 转型
    CODING Compass —— 打造行云流水般的软件工厂
    Nocalhost —— 让云原生开发回归原始而又简单
    CODING 代码资产安全系列之 —— 构建全链路安全能力,守护代码资产安全
    Nocalhost:云原生开发新体验
    使用 Nocalhost 开发 Kubernetes 中的 APISIX Ingress Controller
  • 原文地址:https://www.cnblogs.com/tengpengfei/p/10454015.html
Copyright © 2011-2022 走看看