02 DAO模式设计

DAO模式设计

标签: jdbc


什么是DAO

Data Access Object,数据库访问对象,主要的功能就是用于进行数据操作的CRUD(create,read,update,delete),而不包含任何业务相关的信息。在程序的标准开发架构中属于数据层的操作。

实现了功能的模块化。更有利于代码的维护和升级。

如何编写DAO

DAO可以被继承或直接使用。使用JDBC编写DAO可能会包含的方法:

  • INSERT,UPDATE,DELDETE操作都可以包含在其中 void update(String sql,Object ... args);

  • 查询一条记录,返回对应的对象 <T> T get(Class<T> clazz,String sql,Object ... args);

  • 查询多条记录,返回对应的对象的集合 <T> List<T> getForList(Class<T> clazz,String sql,Object ... args);
  • 返回某条记录的某一个字段的值,或一个统计的值(一共有多少条记录等) <E> E getForValue(String sql,Object ... args);

BeanUtils获取Java类的属性

在JavaEE中,Java类的属性通过getter,setter来定义:get(或set)方法,取出get(或set)后首字母小写后即为Java类的属性

以前所说的属性,也就是成员变量,称之为字段。

操作Java类的属性有一个工具包:beanutils
我们需要在项目中导入beanutils以及logging的jar包
我们通过beanutils工具包的方法来操作属性:
给对象object的属性赋值:

BeanUtils.setProperty(Object bean,String name,Object value);

获取对象object的属性:

Object val = BeanUtils.getProperty(Object bean,String name);

DAO中的方法

增删改操作:update

/**
     * INSERT,UPDATE,DELDETE操作都可以包含在其中
     * @param sql 传入的sql语句
     * @param args 占位符的可变参数
     */
    public void update(String sql, Object... args) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        try {
            connection = JDBCTools.getConnection();
            preparedStatement = connection.prepareStatement(sql);
            for (int i = 0; i < args.length; i++) {
                preparedStatement.setObject(i + 1, args[i]);
            }
            preparedStatement.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCTools.release(null, preparedStatement, connection);
        }
    }

查询单条记录操作:get

 /**
     * 查询一条记录,返回对应的对象
     * @param clazz 要查询的对象的类
     * @param sql 传入的sql语句
     * @param args 占位符的可变参数
     * @param <T> 泛型
     * @return
     */
    public <T> T get(Class<T> clazz, String sql, Object... args) {
        T entity = null;
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        try {
            //1. 获取Connection连接
            connection = JDBCTools.getConnection();
            //2. 获取PreparedStatement对象
            preparedStatement = connection.prepareStatement(sql);
            //3. 填充占位符
            for (int i = 0; i < args.length; i++) {
                preparedStatement.setObject(i + 1, args[i]);
            }
            //4. 进行查询,达到结果集
            resultSet = preparedStatement.executeQuery();
            //5. 创建一个Map
            Map<String, Object> map = new HashMap<>();
            //6. 得到ResultSetMetaData对象
            ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
            //7. 处理结果集,指针向下移
            //while循环没进来,把前面的if(resultSet.next())去掉就好了
            while (resultSet.next()) {
                //8. 得到ResultSetMetaData的列数
                int columnCount = resultSetMetaData.getColumnCount();
                //9. 由ResultSetMetaData得到每一个列的别名,由ResultSet得到具体每一列的值
                for (int i = 0; i < columnCount; i++) {
                    String columnLabel = resultSetMetaData.getColumnLabel(i + 1);
                    Object columnValue = resultSet.getObject(i + 1);

                    //10.填充Map
                    map.put(columnLabel, columnValue);
                }

                //11. 利用反射创建Class实体对象
                entity = clazz.newInstance();
                //12. 遍历Map对象,用反射填充对象的属性值
                for (Map.Entry<String, Object> entry : map.entrySet()) {
                    String propertyName = entry.getKey();
                    Object value = entry.getValue();

                    //ReflectionUtils.setFieldValue(entity, propertyName, value);
                    BeanUtils.setProperty(entity, propertyName, value);
                }
            }

        } catch (SQLException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCTools.release(resultSet, preparedStatement, connection);
        }
        return entity;
    }

查询多条记录操作getForList

 /**
     * 查询多条记录,返回对应的对象的集合
     * @param clazz 要查询的对象的类
     * @param sql 传入的sql语句
     * @param args 占位符的可变参数
     * @param <T> 泛型
     * @return
     */
    public <T> List<T> getForList(Class<T> clazz, String sql, Object... args) {
        List<T> list = new ArrayList<>();
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;

        try {
            //1. 建立Connection连接
            connection = JDBCTools.getConnection();

            //2. 创建PreparedStatement对象
            preparedStatement = connection.prepareStatement(sql);

            //3. 填充占位符
            for (int i = 0; i < args.length; i++) {
                preparedStatement.setObject(i + 1, args[i]);
            }

            //4. 查询得到结果集
            resultSet = preparedStatement.executeQuery();

            //5. 准备多个Map:List<Map<String,Object>>,每一个Map对应一条查询记录
            List<Map<String, Object>> values = new ArrayList<>();

            //6. 得到ResultSetMetaData对象
            ResultSetMetaData resultSetMetaData = resultSet.getMetaData();

            Map<String, Object> map = null;
            //7. 处理ResultSet,使用while循环
            while (resultSet.next()) {
                //集合中的每一个map
                map = new HashMap<>();

                //8. 得到ResultSetMetaData的列数
                int columnCount = resultSetMetaData.getColumnCount();

                //9. 由ResultSetMetaData得到字段的别名,由ResultSet得到字段的值
                for (int i = 0; i < columnCount; i++) {
                    String columnLabel = resultSetMetaData.getColumnLabel(i + 1);
                    Object value = resultSet.getObject(i + 1);

                    //10. 填充Map对象
                    map.put(columnLabel, value);
                }

                //11. 把填充好的Map对象放入List中
                values.add(map);
            }

            //12. 判断List是否为空集合,若不为空,则遍历List,得到一个一个的Map对象
            //再把Map对象转为一个Class参数对应的Object对象
            T bean = null;

            if (values.size() > 0) {

                //遍历列表中的map
                for (Map<String, Object> m : values) {
                    //每找到一个map,就要利用反射创建一个实例对象
                    bean = clazz.newInstance();
                    //通过遍历map中的键值对,给实例对象赋值
                    for (Map.Entry<String, Object> entry : m.entrySet()) {
                        String propertyName = entry.getKey();
                        Object value = entry.getValue();
                        //通过beanUtils给对象的属性赋值
                        BeanUtils.setProperty(bean, propertyName, value);
                    }

                    //13.把Object对象放入到List中
                    list.add(bean);

                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCTools.release(resultSet, preparedStatement, connection);
        }

        return list;
    }

重构getForList

将很多方法抽取出来,重构

/**
     * 查询多条记录,返回对应的对象的集合
     * @param clazz 要查询的对象的类
     * @param sql 传入的sql语句
     * @param args 占位符的可变参数
     * @param <T> 泛型
     * @return
     */
    public <T> List<T> getForList(Class<T> clazz, String sql, Object... args) {
        List<T> list = new ArrayList<>();
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;

        try {
            //1. 得到结果集
            connection = JDBCTools.getConnection();
            preparedStatement = connection.prepareStatement(sql);
            for (int i = 0; i < args.length; i++) {
                preparedStatement.setObject(i + 1, args[i]);
            }
            resultSet = preparedStatement.executeQuery();

            //2. 处理结果集,得到Map的一个List,其中一个Map对象对应一条记录
            //其中Map的key为resultSet中列的别名,Map的value为列的值。
            List<Map<String, Object>> values = handleResultSetToMapList(resultSet);

            //3. 把Map的List转为clazz对应的list
            // 其中Map的key为clazz对应的对象的propertyName,Map的值为clazz对应的对象的propertyValue
            list = transfterMapListToBeanList(clazz, values);

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCTools.release(resultSet, preparedStatement, connection);
        }

        return list;
    }


    /**
     * 将Map列表中的键值对赋给list对象中
     * @param clazz
     * @param values
     * @param <T>
     * @return
     * @throws InstantiationException
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     */
    private <T> List<T> transfterMapListToBeanList(Class<T> clazz, List<Map<String, Object>> values) throws InstantiationException, IllegalAccessException, InvocationTargetException {

        List<T> result = new ArrayList<>();

        T bean = null;
        System.out.println(values.size());
        if (values.size() > 0) {

            //遍历列表中的map
            for (Map<String, Object> m : values) {
                //把它从内层的for循环拿出来
                bean = clazz.newInstance();
                //遍历map中的键值对
                for (Map.Entry<String, Object> entry : m.entrySet()) {
                    String propertyName = entry.getKey();
                    Object value = entry.getValue();

                    BeanUtils.setProperty(bean, propertyName, value);
                }

                //13.把Object对象放入到List中
                result.add(bean);

            }
        }
        return result;
    }

    /**
     * 处理结果集,得到Map的一个List,其中一个Map对象对应一条记录
     * @param resultSet 结果集
     * @return list
     * @throws SQLException
     */
    private List<Map<String, Object>> handleResultSetToMapList(ResultSet resultSet) throws SQLException {
        //5. 准备多个Map:List<Map<String,Object>>,每一个Map对应一条查询记录
        List<Map<String, Object>> values = new ArrayList<>();

        //6. 得到ResultSetMetaData对象
        //ResultSetMetaData resultSetMetaData = resultSet.getMetaData();

        //调用方法
        List<String> columnLabels = getColumnLabels(resultSet);

        Map<String, Object> map = null;

        //7. 处理ResultSet,使用while循环
        while (resultSet.next()) {
            map = new HashMap<>();

            //8. 得到ResultSetMetaData的列数
            //int columnCount = resultSetMetaData.getColumnCount();

            //9. 由ResultSetMetaData得到字段的别名,由ResultSet得到字段的值
            for (String columnLabel : columnLabels) {
                //String columnLabel = resultSetMetaData.getColumnLabel(i + 1);
                Object value = resultSet.getObject(columnLabel);

                //10. 填充Map对象
                map.put(columnLabel, value);
            }

            //11. 把填充好的Map对象放入List中
            values.add(map);
        }
        return values;
    }

    /**
     * 获取结果集的ColumnLabel对应的集合List
     * @param resultSet
     * @return
     * @throws SQLException
     */
    private List<String> getColumnLabels(ResultSet resultSet) throws SQLException {
        List<String> labels = new ArrayList<>();
        ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
        for (int i = 0;i < resultSetMetaData.getColumnCount();i++) {
            labels.add(resultSetMetaData.getColumnLabel(i+1));
        }
        return labels;
    }

重构get方法

利用getForList方法重构get方法

    /**
     * 查询一条记录,返回对应的对象
     * @param clazz 要查询的对象的类
     * @param sql 传入的sql语句
     * @param args 占位符的可变参数
     * @param <T> 泛型
     * @return
     */
    public <T> T get(Class<T> clazz, String sql, Object... args) {
        List<T> result = getForList(clazz,sql,args);
        if (result.size() > 0) {
            return result.get(0);
        }
        return null;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值