IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> JDBC七:DAO -> 正文阅读

[Java知识库]JDBC七:DAO

DAO

引导

  1. DAO的思想在于由通用方法组成的BaseDAO、具体类的接口及实现类,形成一套调用接口

  2. 通过反射及泛型的应用,对BaseDAO进行优化。

    反射优化部分参考Java六十九: 反射

一、概述

  1. DAO:Data Access Object,数据访问的类或接口,包括了对数据的CRUD,而不包含任何业务相关的信息,也称作:BaseDAO
  2. 作用:为了实现功能的模块化,更有利于代码的维护和升级

二、具体表的DAO

  1. BaseDAO

    里面放增删改查的通用方法

    package optimization;
    
    import bean.Customers;
    import jdbcutils.JdbcUtils;
    
    import java.lang.reflect.*;
    import java.sql.*;
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * @author e_n
     * @version 1.0.0
     * @ClassName BaseDAO.java
     * @Description 优化后的BaseDAO,可以利用泛型进行通用化,简化内方法的调用
     * @CreateTime 2022/01/30 16:13
     */
    public abstract class BaseDAO<T> {
        private Class<T> clazz = null;
        // 在代码块中对clazz进行赋值,当前对象的父类的泛型
        {
            // this是该类的实例对象
            Type genericSuperclass = this.getClass().getGenericSuperclass();
            ParameterizedType paramType = (ParameterizedType) genericSuperclass;
            Type[] typeArguments = paramType.getActualTypeArguments();
            clazz = (Class<T>) typeArguments[0];
        }
        /**
         * @title update
         * @Description 增删改通用方法
         * @author e_n
         * @param conn
         * @param sql
         * @param args
         * @return int
         * @throws
         * @CreateTime 2022/2/2 22:13
         */
        public int update(Connection conn, String sql, Object...args) {
            PreparedStatement ps = null;
            try {
                // 1.sql预编译
                ps = conn.prepareStatement(sql);
                // 2.填充占位符
                for (int i = 0; i < args.length; i++) {
                    ps.setObject(i+1,args[i]);
                }
                // 3.执行sql
                return ps.executeUpdate();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            } finally {
                // 4.关闭连接。因为conn是以参数形式引入的,所以无法关闭,故在关闭程序中的conn参数为null
                JdbcUtils.closeResource(null,ps);
            }
            return 0;
        }
    
        /**
         * @title CommonRetrieve
         * @Description 返回多条记录的通用查询方法
         * @author e_n
         * @param conn
         * @param sql
         * @param args
         * @return java.util.List<T>
         * @throws
         * @CreateTime 2022/2/2 22:13
         */
        public List<T> CommonRetrieve(Connection conn, String sql, Object...args)  {
            PreparedStatement ps = null;
            ResultSet rs = null;
            try {
                // 1.预编译sql,生成PreparedStatement对象
                ps = conn.prepareStatement(sql);
                // 2.填充占位符
                for (int i = 0; i < args.length; i++) {
                    ps.setObject(i+1,args[i]);
                }
                // 3.执行并返回结果集
                rs = ps.executeQuery();
                // 4.处理结果集
                // 4.1 创建该结果集的元数据,通过元数据获取结果集中数据的信息
                ResultSetMetaData rsmd = rs.getMetaData();
                // 4.2 获取结果集中列的个数
                int columnCount = rsmd.getColumnCount();
                // 4.3 创建用于存储结果集中多条记录的集合
                ArrayList<T> tSet = new ArrayList<>();
                while (rs.next()) {
                    // 4.4 处理该行记录的每一个字段
                    // 4.4.1 创建该行记录在JavaBean中类的对象,此处用泛型实现
                    T t = clazz.newInstance();
                    // 4.4.2 利用通过元素据获得的结果集中列的个数,结合for循环对结果集中的列进行遍历
                    for (int i = 0; i < columnCount; i++) {
                        // 4.4.3 通过结果集对象获取该字段的值
                        Object columnValue = rs.getObject(i + 1);
                        // 4.4.4 通过元素据获取该字段的别(列)名,该列名与该行记录对应的对象中的属性名相同
                        String columnLabel = rsmd.getColumnLabel(i+1);
                        // 4.4.5 通过反射,给Customers对象中对应的属性赋值,实现将结果集中的数据存储到对象中
                        Field field = clazz.getDeclaredField(columnLabel);
                        // 确保私有属性可以访问
                        field.setAccessible(true);
                        // 给该字段对应的属性赋值
                        field.set(t,columnValue);
                    }
                    // 4.4.6 将此次循环产生的对象加入新建的集合中
                    tSet.add(t);
                }
                return tSet;
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                // 6.关闭资源
                JdbcUtils.closeResource(null,ps,rs);
            }
            return null;
        }
    
        /**
         * @title singleCommonRetrieve
         * @Description 返回单条记录的通用查询方法
         * @author e_n
         * @param conn
         * @param sql
         * @param args
         * @return T
         * @throws
         * @CreateTime 2022/2/2 22:14
         */
        public T singleCommonRetrieve(Connection conn, String sql, Object...args)  {
            PreparedStatement ps = null;
            ResultSet rs = null;
            try {
                // 1.预编译sql,生成PreparedStatement对象
                ps = conn.prepareStatement(sql);
                // 2.填充占位符
                for (int i = 0; i < args.length; i++) {
                    ps.setObject(i+1,args[i]);
                }
                // 3.执行并返回结果集
                rs = ps.executeQuery();
                // 4.处理结果集
                // 4.1 创建该结果集的元数据,通过元数据获取结果集中数据的信息
                ResultSetMetaData rsmd = rs.getMetaData();
                // 4.2 获取结果集中列的个数
                int columnCount = rsmd.getColumnCount();
                if (rs.next()) {
                    // 4.3 处理该行记录的每一个字段
                    // 4.3.1 创建该行记录在JavaBean中类的对象,此处用泛型实现
                    T t = clazz.newInstance();
                    // 4.3.2 利用通过元素据获得的结果集中列的个数,结合for循环对结果集中的列进行遍历
                    for (int i = 0; i < columnCount; i++) {
                        // 4.3.3 通过结果集对象获取该字段的值
                        Object columnValue = rs.getObject(i + 1);
                        // 4.3.4 通过元素据获取该字段的别(列)名,该列名与该行记录对应的对象中的属性名相同
                        String columnLabel = rsmd.getColumnLabel(i+1);
                        // 4.3.5 通过反射,给Customers对象中对应的属性赋值,实现将结果集中的数据存储到对象中
                        Field field = clazz.getDeclaredField(columnLabel);
                        // 确保私有属性可以访问
                        field.setAccessible(true);
                        // 给该字段对应的属性赋值
                        field.set(t,columnValue);
                    }
                return t;
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                // 6.关闭资源
                JdbcUtils.closeResource(null,ps,rs);
            }
            return null;
        }
    
        /**
         * @title getValue
         * @Description 用于查询特殊值的通用方法(聚合函数)
         * @author e_n
         * @param conn
         * @param sql
         * @param args
         * @return E
         * @throws
         * @CreateTime 2022/2/2 22:14
         */
        public <E> E getValue(Connection conn, String sql, Object...args) {
            PreparedStatement ps = null;
            ResultSet rs = null;
            try {
                // 1.sql预编译
                ps = conn.prepareStatement(sql);
                // 2.填充占位符
                for (int i = 0; i < args.length; i++) {
                    ps.setObject(i+1,args[i]);
                }
                // 3.执行sql
                rs = ps.executeQuery();
                // 4.返回值
                if (rs.next()) {
                    return (E) rs.getObject(1);
                }
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            } finally {
                // 4.关闭连接。因为conn是以参数形式引入的,所以无法关闭,故在关闭程序中的conn参数为null
                JdbcUtils.closeResource(null,ps,rs);
            }
            return null;
        }
    }
    
    
  2. 接口

    从逻辑上,为了使代码的格式更加规范,增加一个接口,用于规范针对该表的常用操作

    package optimization;
    
    import bean.Customers;
    
    import java.sql.Connection;
    import java.util.Date;
    import java.util.List;
    
    /**
     * @author e_n
     * @version 1.0.0
     * @ClassName CustomerDAO.java
     * @Description
     * @CreateTime 2022/01/30 17:31
     */
    public interface CustomerDAO {
    
        /**
         * @title insert
         * @Description 将cust对象添加到数据库中
         * @author e_n 
         * @param conn
         * @param cust
         * @return void
         * @throws 
         * @CreateTime 2022/2/2 21:38 
         */
        void insert(Connection conn, Customers cust);
        /**
         * @title deleteById
         * @Description 根据指定的id,删除数据表中的一条记录
         * @author e_n 
         * @param conn
         * @param id
         * @return void
         * @throws 
         * @CreateTime 2022/2/2 21:34 
         */
        void deleteById(Connection conn, int id);
        
        /**
         * @title updateById
         * @Description 针对内存中的cust对象,去修改数据表中的记录
         * @author e_n 
         * @param conn
         * @param cust
         * @return void
         * @throws 
         * @CreateTime 2022/2/2 21:35 
         */
        void updateById(Connection conn, Customers cust);
    
        /**
         * @title getCustomerById
         * @Description 针对指定的id查询得到对应的Customer对象
         * @author e_n 
         * @param conn
         * @param id
         * @return bean.Customers
         * @throws 
         * @createTime 2022/2/2 21:30 
         */
        Customers getCustomerById(Connection conn, int id);
    
        /**
         * @title getAll
         * @Description 获取数据表中的所有记录
         * @author e_n 
         * @param conn
         * @return java.util.List<bean.Customers>
         * @throws 
         * @createTime 2022/2/2 21:29 
         */
        List<Customers> getAll(Connection conn);
        /**
         * @title getCount
         * @Description 返回数据表中数据的条目数
         * @author e_n
         * @param conn
         * @return java.lang.Long
         * @throws
         * @CreateTime 2022/2/2 21:52
         */
        Long getCount(Connection conn);
        /**
         * @title getMaxBirth
         * @Description 返回数据表中最大的生日
         * @author e_n
         * @param conn
         * @return java.util.Date
         * @throws
         * @CreateTime 2022/2/2 21:53
         */
        Date getMaxBirth(Connection conn);
        
    }
    
  3. 实现类

    继承BaseDAO,实现该接口,通过调用BaseDAO中的通用方法,实现接口中的抽象方法

    package optimization;
    
    import bean.Customers;
    
    import java.sql.Connection;
    import java.util.Date;
    import java.util.List;
    
    /**
     * @author e_n
     * @version 1.0.0
     * @ClassName CustomerDAOImpl.java
     * @Description
     * @CreateTime 2022/02/02 21:55
     */
    public class CustomerDAOImpl extends BaseDAO<Customers> implements CustomerDAO {
        /**
         * @param conn
         * @param cust
         * @return void
         * @throws
         * @title insert
         * @Description 将cust对象添加到数据库中
         * @author e_n
         * @CreateTime 2022/2/2 21:38
         */
        @Override
        public void insert(Connection conn, Customers cust) {
            String sql = "insert into customers(name,email,birth) values(?,?,?)";
            update(conn,sql,cust.getName(),cust.getEmail(),cust.getBirth());
        }
    
        /**
         * @param conn
         * @param id
         * @return void
         * @throws
         * @title deleteById
         * @Description 根据指定的id,删除数据表中的一条记录
         * @author e_n
         * @CreateTime 2022/2/2 21:34
         */
        @Override
        public void deleteById(Connection conn, int id) {
            String sql = "delete from customers where id = ?";
            update(conn,sql,id);
        }
    
        /**
         * @param conn
         * @param cust
         * @return void
         * @throws
         * @title updateById
         * @Description 针对内存中的cust对象,去修改数据表中的记录
         * @author e_n
         * @CreateTime 2022/2/2 21:35
         */
        @Override
        public void updateById(Connection conn, Customers cust) {
            String sql = "update customers set name = ?, email = ?, birth = ? where id = ?";
            update(conn,sql,cust.getName(),cust.getEmail(),cust.getBirth(),cust.getId());
        }
    
        /**
         * @param conn
         * @param id
         * @return bean.Customers
         * @throws
         * @title getCustomerById
         * @Description 针对指定的id查询得到对应的Customer对象
         * @author e_n
         * @createTime 2022/2/2 21:30
         */
        @Override
        public Customers getCustomerById(Connection conn, int id) {
            String sql = "select name,email,birth,id from customers where id = ?";
            return singleCommonRetrieve(conn,sql,id);
        }
    
        /**
         * @param conn
         * @return java.util.List<bean.Customers>
         * @throws
         * @title getAll
         * @Description 获取数据表中的所有记录
         * @author e_n
         * @createTime 2022/2/2 21:29
         */
        @Override
        public List<Customers> getAll(Connection conn) {
            String sql = "select name,email,birth,id from customers";
            return CommonRetrieve(conn,sql);
        }
    
        /**
         * @param conn
         * @return java.lang.Long
         * @throws
         * @title getCount
         * @Description 返回数据表中数据的条目数
         * @author e_n
         * @CreateTime 2022/2/2 21:52
         */
        @Override
        public Long getCount(Connection conn) {
            String sql = "select count(1) from customers ";
            return getValue(conn,sql);
        }
    
        /**
         * @param conn
         * @return java.util.Date
         * @throws
         * @title getMaxBirth
         * @Description 返回数据表中最大的生日
         * @author e_n
         * @CreateTime 2022/2/2 21:53
         */
        @Override
        public Date getMaxBirth(Connection conn) {
            String sql = "select min(birth) from customers";
            return getValue(conn,sql);
        }
    }
    

三、优化

  1. 具体的实现类中都非常明确是操作的哪个表,对应操作类也非常明确,故在实现类中的各个重写方法中的Customer.class参数也可去除,可通过在BaseDAO中增加泛型来解决。在实现类继承BaseDAO后,就指明其泛型为Customer,即可对实现类进行优化
    注:BaseDAO类中的方法存在于该博文中 - - JDBC三:使用PreparedStatement实现CRUD

  2. 在BaseDAO增加泛型后,可将泛型对象 clazz在代码块中进行初始化,从而可将类内各通用方法的参数列表中的Class clazz去除掉,但方法内的clazz仍然可用。

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-02-06 13:41:29  更:2022-02-06 13:43:31 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 9:28:40-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码