• 10.12JDBC之DAO及其实现类


    10.12JDBC之DAO及其实现类

    BaseDAO类

    概念:

    • 封装了针对于数据表的通用操作

    • 因为我们后续不会去造BaseDAO的对象,所以声明为抽象类--->不能够造该对象

    该类包含的函数:

    • 通用的增、删、改操作

    • 通用的查询一条数据操作

    • 通用的查询多条数据操作

    • 支持使用MySQL内置函数操作

    package JDBCDAO;

    import JDBCStatementCRUD.JDBCUtils;

    import java.lang.reflect.Field;
    import java.sql.*;
    import java.util.ArrayList;
    import java.util.List;

    /**
    * 封装了针对于数据表的通用的操作
    * 因为我们后续不会去造BaseDAO的对象,所以声明为抽象类--->不能够造该对象
    * Data(base) Access Object:数据库访问对象
    * @since JDK 1.8
    * @date 2021/10/12
    * @author Lucifer
    */
    public abstract class BaseDAO {
       //外部传入连接
       //通用的增删改查方法--->version 2.0(考虑了事务以后的操作)
       public int update(Connection conn, String sql, Object ...args) {
           PreparedStatement ps = null;
           try {
               //获取链接
               conn = JDBCUtils.getConnection();
               //预编译sql
               ps = conn.prepareStatement(sql);
               //填充占位符--->使用流的形式
               for (int i = 0; i < args.length; i++) {
                   ps.setObject(i + 1, args[i]);
              }
               //执行语句
               return ps.executeUpdate();
          }catch (Exception e) {
               e.printStackTrace();
          }finally {
               //关闭资源
               /*
               1、由于是外部传入的连接,所以不需要关闭Connection连接
                */
               JDBCUtils.closeResource(null, ps);
          }
           return 0;
      }

       /*
       1、将其设置为事务的处理方式。--->将事务作为参数传入函数当中
       注意:
       1、不要再次创建链接Connection
       2、关闭的时候不要关闭连接
       通用查询操作,用于返回数据表中的一条数据(考虑事务操作)
        */
       //仅返回一个对象
       public <T> T getInstance(Connection conn, Class<T> clazz, String sql, Object ...args) {
           PreparedStatement ps = null;
           ResultSet rs = null;
           try {
               //预编译sql
               ps = conn.prepareStatement(sql);
               //填充占位符
               for (int i=0; i<args.length; i++) {
                   ps.setObject(i+1, args[i]);
              }
               //执行sql保存为结果集对象
               rs = ps.executeQuery();

               //获取结果集元数据
               ResultSetMetaData rsmd = rs.getMetaData();
               //获取列数
               int columnCount = rsmd.getColumnCount();
               //获取结果集
               if (rs.next()) {
                   //通过反射获取运行时加载类建立对象的引用--->反射+泛型
                   T t = clazz.newInstance(); //--->任何一个类在提供一个JavaBean对象的时候要提供一个空参的public权限的构造器,在这里使用
                   /*
                   方法当中返回一个t
                   t由当前类决定的
                    */
                   //动态的获取列,列的数量为列数
                   for (int j=0; j<columnCount; j++) {
                       //动态的获取列值--->结果集当中获取列值
                       Object columnValue = rs.getObject(j+1);
                       //获取每列的列名
                       String columnLabel = rsmd.getColumnLabel(j+1);
                       //动态获取加载的类的属性--->获取到域(T类型的)
                       Field field = clazz.getField(columnLabel);
                       //设置私有属性可访问
                       field.setAccessible(true);
                       //将对象属性设置成列值
                       field.set(t, columnValue);
                  }
                   return t;
              }
          }catch (Exception e) {
               e.printStackTrace();
          }finally {
               //关闭资源--->注意不要关闭连接
               JDBCUtils.closeResource(null, ps, rs);
          }
           return null;
      }

       /**
        * 查询一条sql语句返回多个结果集对象
        * 使用List进行封装然后再集中展示
        * @since JDK 1.8
        * @date 2021/09/30
        * @author Lucifer
        */
       //返回多个对象构成的集合
       public <T> List<T> getForList(Connection conn, Class<T> clazz, String sql, Object ...args) {
           PreparedStatement ps = null;
           ResultSet rs = null;
           try {
               //预编译sql
               ps = conn.prepareStatement(sql);
               //填充占位符
               for (int i=0; i<args.length; i++) {
                   ps.setObject(i+1, args[i]);
              }
               //执行sql保存为结果集对象
               rs = ps.executeQuery();

               //获取结果集元数据
               ResultSetMetaData rsmd = rs.getMetaData();
               //获取列数
               int columnCount = rsmd.getColumnCount();
               //创建集合对象--->用于存储查询出的结果集对象
               ArrayList<T> list = new ArrayList<T>();
               //查询多条语句使用循环进行查询
               while (rs.next()) {
                   T t = clazz.newInstance();
                   //处理结果集每一行数据的每一列
                   for (int j=0; j<columnCount; j++) {
                       //获取列值
                       Object columnValue = rs.getObject(j+1);

                       //获取列名
                       String columnLabel = rsmd.getColumnLabel(j+1);
                       //动态获取运行类
                       Field field = clazz.getDeclaredField(columnLabel);
                       field.setAccessible(true);
                       field.set(t, columnValue);
                  }
                   //将t对象添加进入集合数组
                   list.add(t);
                   /*
                   查询未找到
                   1、抛异常了
                   2、没有数据了
                    */
              }
               return list;
          }catch (Exception e) {
               e.printStackTrace();
          }finally {
               //关闭资源(注意不要关闭连接)
               JDBCUtils.closeResource(null, ps, rs);
          }
           return null;
      }

       //针对于使用mysql内置的函数使用的查询方法--->返回的类型是泛型
       public <E> E getValue(Connection conn, String sql, Object ...args) {
           PreparedStatement ps = null;
           ResultSet rs = null;
           try {
               //预编译sql
               ps = conn.prepareStatement(sql);
               //填充占位符
               for (int i=0; i<args.length; i++) {
                   //通过setObject方法进行添加
                   ps.setObject(i+1, args[i]);
              }

               //查询结果放入结果集
               rs = ps.executeQuery();
               if (rs.next()) {
                   return (E) rs.getObject(1);
              }
          }catch (SQLException e) {
               e.printStackTrace();
          }finally {
               //关闭资源
               JDBCUtils.closeResource(null, ps, rs);
          }
           return null;
      }
    }

    其他的DAO实现类

    通过接口定义规范,通过抽象类定义公共的方法

    package JDBCDAO;

    import JDBCBean.Customer;

    import java.sql.Connection;
    import java.util.Date;
    import java.util.List;

    /**
    * 此接口用语规范针对于Customer表的常用操作
    * 针对于Customer这个表只提供这些功能
    * @since JDK 1.8
    * @date 2021/10/12
    * @author Lucfier
    */
    public interface CustomerDAO {
       //将cust对象添加到数据库中
       void insert(Connection conn, Customer cust);

       //删除数据--->针对指定的id进行删除
       void deleteById(Connection conn, int id);

       //修改数据--->针对内存中的cust对象修改数据表中的指定记录
       void update(Connection conn, Customer cust);

       //查询数据--->根据指定的id查询指定的customer对象
       Customer getCustomerById(Connection conn, int id);

       //查询表中的所有记录构成的集合
       List<Customer> getAll(Connection conn);

       //使用mysql的内置函数进行查询操作,返回数据表中所有的数据数量
       Long getCount(Connection conn);

       //返回数据表中的最大的生日数据
       Date getMaxBirth(Connection conn);
    }

    操作表的具体的实现方法

    package JDBCDAO;

    import JDBCBean.Customer;

    import java.sql.Connection;
    import java.util.Date;
    import java.util.List;

    /**
    * 针对于Customer表的具体的实现
    * 继承抽象类,实现接口
    * @since JDK 1.8
    * @date 2021/10/12
    * @author Lucfier
    */
    public class CustomerDAOImpl extends BaseDAO implements CustomerDAO {
       @Override
       public void insert(Connection conn, Customer cust) {
           //根据父类的方法构造参数
           String sql = "insert into customers(name, email, birth) values(?, ?, ?);";

           //调用父类当中的update方法
           //args是填充的占位符,占位符取决于对象。所以通过对象的get方法去获取
           //这个get方法由JavaBean对象提供
           update(conn, sql, cust.getName(),cust.getEmail(),cust.getBirth());
           /*如果需要返回值需要修改接口当中的返回值*/
      }

       @Override
       public void deleteById(Connection conn, int id) {
           //根据方法构造参数
           String sql = "delete from customer where id = ?;";

           //调用父类当中的update方法--->id由形参确定
           update(conn, sql, id);
      }

       @Override
       public void update(Connection conn, Customer cust) {
           //构造sql
           String sql = "update customers set name = ?, email = ?, birth = ? where id = ?;";

           //调用父类当中的方法--->根据表
           update(conn, sql, cust.getName(),cust.getEmail(),cust.getBirth(),cust.getId());
      }

       @Override
       public Customer getCustomerById(Connection conn, int id) {
           //根据父类当中的方法构造参数
           String sql = "select id,name,email,birth from customers where id = ?;";

           //调用父类当中的getInstance方法
           Customer customer = getInstance(conn, Customer.class, sql, id);
           return customer;
      }

       @Override
       public List<Customer> getAll(Connection conn) {
           //书写sql
           String sql = "select id,name,email,birth from customers;";

           //调用父类当中的方法.没有过滤条件所以没有可变形参
           List<Customer> list = getForList(conn, Customer.class, sql);
           return list;
      }

       @Override
       public Long getCount(Connection conn) {
           //书写sql
           String sql = "select count(*) from customers;";

           //调用父类当中的方法直接作为返回值
           return getValue(conn, sql);
      }

       @Override
       public Date getMaxBirth(Connection conn) {
           //书写sql
           String sql = "select max(birth) from customers;";

           //调用父类当中的方法直接作为返回值
           return getValue(conn, sql);
      }
    }

    测试类

    CustomerDAOImpl类下右键--->go to--->Test可以直接创建方法(还可以选择测试框架)

    package JDBCDAO;

    import JDBCBean.Customer;
    import JDBCStatementCRUD.JDBCUtils;
    import org.testng.annotations.Test;

    import java.sql.Connection;
    import java.util.Date;
    import java.util.List;

    import static org.testng.Assert.*;

    public class CustomerDAOImplTest {

       //创建CustomerDAOImpl对象引用
       private CustomerDAOImpl dao = new CustomerDAOImpl();

       @Test
       public void testInsert() {
           Connection conn = null;
           try {
               //获取连接
               conn = JDBCUtils.getConnection();
               //创建一个Customer对象--->实际过程当中应该把字符串解析成long类型传进测试方法中
               Customer cust = new Customer(1, "JkB", "JunkingBoy@163.com", new Date(65534512354L));
               //测试方法
               dao.insert(conn, cust);
               System.out.println("插入成功!");
          }catch (Exception e){
               e.printStackTrace();
          }finally {
               //关闭资源
               JDBCUtils.closeResource(conn, null);
          }
      }

       @Test
       public void testDeleteById() {
           Connection conn = null;
           try {
               //获取连接
               conn = JDBCUtils.getConnection();

               dao.deleteById(conn, 13);

               System.out.println("删除成功!");
          }catch (Exception e){
               e.printStackTrace();
          }finally {
               //关闭资源
               JDBCUtils.closeResource(conn, null);
          }
      }

       @Test
       public void testUpdate() {
           Connection conn = null;
           try {
               //获取连接
               conn = JDBCUtils.getConnection();

               //创建修改对象
               Customer cust = new Customer(18, "JKB", "Junkingboy@163.com", new Date(45651231645L));
               dao.update(conn, cust);

               System.out.println("修改成功!");
          }catch (Exception e){
               e.printStackTrace();
          }finally {
               //关闭资源
               JDBCUtils.closeResource(conn, null);
          }
      }

       @Test
       public void testGetCustomerById() {
           Connection conn = null;
           try {
               //获取连接
               conn = JDBCUtils.getConnection();

               Customer customer = dao.getCustomerById(conn, 19);

               System.out.println(customer);
          }catch (Exception e){
               e.printStackTrace();
          }finally {
               //关闭资源
               JDBCUtils.closeResource(conn, null);
          }
      }

       @Test
       public void testGetAll() {
           Connection conn = null;
           try {
               //获取连接
               conn = JDBCUtils.getConnection();

               //直接将结果获取为一个list
               List<Customer> list = dao.getAll(conn);

               //循环遍历输出
               list.forEach(System.out::println);
          }catch (Exception e){
               e.printStackTrace();
          }finally {
               //关闭资源
               JDBCUtils.closeResource(conn, null);
          }
      }

       @Test
       public void testGetCount() {
           Connection conn = null;
           try {
               //获取连接
               conn = JDBCUtils.getConnection();

               Long count = dao.getCount(conn);

               System.out.println("表中的记录数为:" + count);
          }catch (Exception e){
               e.printStackTrace();
          }finally {
               //关闭资源
               JDBCUtils.closeResource(conn, null);
          }
      }

       @Test
       public void testGetMaxBirth() {
           Connection conn = null;
           try {
               //获取连接
               conn = JDBCUtils.getConnection();

               Date maxBirth = dao.getMaxBirth(conn);

               System.out.println("最大生日为:" + maxBirth);
          }catch (Exception e){
               e.printStackTrace();
          }finally {
               //关闭资源
               JDBCUtils.closeResource(conn, null);
          }
      }
    }

    上面实现的是数据库交互的业务层面

    • 后期的表比较对只需要实现对于的接口和实现类即可

    • 后期增加的功能先要增加接口当中的方法。再在实现类当中提供方法

    It's a lonely road!!!
  • 相关阅读:
    Sql Server 2008 为开发带来的新特性
    MSMQ 与ESB
    面向服务架构(SOA)和企业服务总线(ESB)
    IBM网站 构建您的SOA 系列文章
    Visual Studio 2008 和 .NET Framework 3.5 Training Kit
    模式与实践 系列发布WCF Security Guidance 1.0
    跟NHibernate之夏一起学习NHibernate
    ORACLE一些不常用的脚本
    ORACLE已建表能否创建分区
    Access数据库问题锦集
  • 原文地址:https://www.cnblogs.com/JunkingBoy/p/15399220.html
Copyright © 2020-2023  润新知