day06-04-jdbc-rowmapper

两种封装执行sql的方式

方式一:技术手段《泛型+反射》,核心区别:赋值流程自己(在公共方法内)实现

方式二:设计手段,抽象,核心区别:赋值流程自己,谁调用,谁实现

package day06;
/*
crud 增删改查

 */

import day05.jdbc.MysqlUtil;
import day05.jdbc.TbUser;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class DaoDemo01 {
    public static void main(String[] args) throws Exception {
        String sql ="select * from auth_group";
        List<TbUser> tbUsers = testDao(sql, null, TbUser.class);
        System.out.println(tbUsers);


        // RowMapper思想
        // 区别:反射的方法,实现对象的赋值,在我们写的统一方法里,统一处理供别人调用
        // 区别:RowMapper方法,谁调用我们,谁就要实现接口里面对象赋值的方法(匿名内部类)
        // 抽象:接口+抽象类
        // 第三个参数,传rowMapper接口,
        // rowMapper接口,这里使用匿名内部类
        // new RowMapper<TbUser>() {....});这里是一行代码(这里用的匿名内部类)
        List<TbUser> tbUsers1 = testRowMapper(sql, null, new RowMapper<TbUser>() {

            // 重写map
            @Override
            public TbUser map(ResultSet rs) throws SQLException {
                TbUser tbUser = new TbUser();
                // 给tbUser赋值
                tbUser.setId(rs.getLong(1));
                tbUser.setName(rs.getString(2));
                return tbUser;
            }
        });
        System.out.println("tbUsers1 = " + tbUsers1);

    }


    /**
     * 根据Sql语句,获取对象集合 《泛型+反射》,技术手段
     * @param sql
     * @param params sql语句的参数,参数的顺序需要使用方自己控制
     * @param cls 对象的class
     * @param <T> 对象的类型
     * @return List<T>
     * @throws Exception
     */
    public static <T> List<T> testDao(String sql,List<Object> params,Class<T> cls) throws Exception {
        // 静态方法的泛型
        // 传参,sql和sql里面的变量
        //Class<T> cls,拿到一个类的Class,通过反射然后构建对象
        //拿到对象的属性字段,然后给属性设置值

        //1、建立连接
        Connection conn = MysqlUtil.getConn();
        //2、预编译
        PreparedStatement ps = conn.prepareStatement(sql);
        if (params!=null){
            // 给sql语句设置参数,参数的顺序使用方自己控制
            for (int i=0;i< params.size();i++){
                // jdbc 参数从1开始数,所以是i+1
                ps.setObject(i+1,params.get(i));
            }
        }

        // 3、运行sql,得到结果集
        ResultSet rs = ps.executeQuery();
        // 集合
        List<T> list =new ArrayList<>();
        while (rs.next()){
            // 通过class,利用反射,构建一个T对象
            // 注意,这个T类,一定要有无参构造器
            T t = cls.newInstance();
            // 通过反射,得到T这个类所有的属性/字段
            Field[] fields = cls.getDeclaredFields();
            // 遍历属性,给t的属性赋值
            for (Field field:fields){
                // 得到属性field的名字,根据field的名字作为列名,在结果集rs中取对应的值
                // 注意:
                String fieldName =field.getName();//属性/字段的名称
                field.setAccessible(true);//设置字段可访问的权限

                //在结果集中,通过列名fileName,来或者对应的值
                // 我们不知道具体是什么类,所以我们用Object
                // 根据列名在结果集中取值,使用属性名作为列名
                // 注意:类T的属性名要与数据库列的字段名称保持一致
                Object object = rs.getObject(fieldName);

                //给对象的当前属性设置值
                //这里涉及到3个数据,field.set(t,object),里面第一个参数传的是实例,
                // 第二个参数是给当前的属性设置的值
                // 当前是什么属性?我们就在遍历for (Field field:fields)属性的循环里,取的当前的属性
                field.set(t,object);

            }
            // 给存放结果集的集合,添加对象
            list.add(t);

        }
        MysqlUtil.close(conn);//关闭数据库连接
        return list;
    }
    //---------------------rowMapper---------------
    //定义一个接口
    // 泛型 T
    interface RowMapper<T>{
        T map(ResultSet rs) throws SQLException;

    }

    /**
     * 《泛型+抽象》设计手段,抽象的概念,封装
     * @param sql
     * @param params
     * @param rowMapper
     * @param <T>
     * @return
     * @throws SQLException
     */
    // 泛型
    // 这里不用class反射,用RowMapper<T>接口
    public static <T> List<T> testRowMapper(String sql,List<Object> params,RowMapper<T> rowMapper) throws SQLException{
        // 建立连接
        Connection conn = MysqlUtil.getConn();
        // 预编译
        PreparedStatement ps = conn.prepareStatement(sql);
        if (params!=null){
            // 给sql语句设置参数,参数的顺序使用方自己控制
            for (int i=0;i< params.size();i++){
                // jdbc 参数从1开始数,所以是i+1
                ps.setObject(i+1,params.get(i));
            }
        }

        //结果集
        ResultSet rs = ps.executeQuery();
        // 创建一个集合,来接收执行sql后的结果集
        List<T> list = new ArrayList<>();
        while (rs.next()){
            // rowMapper的map方法,传rs,得到一个t
            T t = rowMapper.map(rs);
            list.add(t);
        }
        return list;

    }
}

上一篇:day06-14-stream中间操作


下一篇:Day06