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);
      }
  }
}

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

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

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

posted @ 2021-10-12 19:12  俊king  阅读(79)  评论(0编辑  收藏  举报