欢迎光临散文网 会员登陆 & 注册

尚硅谷JDBC实战教程(2023最新版jdbc,JDK17+MySQL8)

2023-06-12 17:53 作者:瑞龙9  | 我要投稿
package com.lyb.utils;

import org.junit.Test;

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


public class BaseDao {
    /*
    对非DQL的封装
     */
    public int executeUpdate(String sql, Object... params) throws SQLException {
        Connection connection = DruidUtils.getConnection();
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        for (int i = 1; i <= params.length; i++) {//注意从一开始,因为参数就是从1开始。
            preparedStatement.setObject(i, params[i - 1]);//注意这里要i-1
        }
        int i = preparedStatement.executeUpdate();
        //是否回收连接,需要考虑是不是事务
        if (connection.getAutoCommit()) {//如果自动提交的话,没有事务,则我们关闭连接
            DruidUtilsV2.CloseConnection();
        }
        //如果是手动提交的话,交给业务层去关闭。
        return i;
    }

    /**
     * 对DQL的封装
     *将查询结果封装到实体类集合。
     * @param clazz 查询结果集对应的实体类的class对象
     * @param sql 查询语句,要求列名或者别名等于实体类的属性名。 u_id as id  => id
     * @param params 占位符的值,用来替换?
     * @return 查询的实体类集合
     * @param <T> 结果的类型。
     * @throws Exception
     */
    public <T> List<T> executeQuery(Class<T> clazz, String sql, Object... params) throws Exception {//Class对象是用反射造对象
        Connection connection = DruidUtilsV2.getConnection();//1.2.用工具类注册驱动并创建连接对象
        PreparedStatement preparedStatement = connection.prepareStatement(sql);//3.创建PreparedStatement对象
        //4.SQL语句是由外部传入的sql
        if (params != null && params.length != 0) {//判断方法传入的参数是否满足条件后,5.占位符赋值
            for (int i = 1; i <= params.length; i++) {//根据占位符赋值的数量进行占位符赋值
                preparedStatement.setObject(i, params[i - 1]);//因为占位符是从1开始,所以上面i= 1开始.
                //传入的值的数组是从params[0] 到 params[i-1]
            }
        }
        ResultSet resultSet = preparedStatement.executeQuery();//6.执行SQL语句并返回结果集
        //7.结果集解析
        ResultSetMetaData metaData = resultSet.getMetaData();//ResultSetMetaData对象存储了resultSet结果集的列名信息,数量等
        int columnCount = metaData.getColumnCount();//获取结果集中列的数量
        List<T> list = new ArrayList<>();//返回的数组对象
        while (resultSet.next()) {//next()一次是一行
            Constructor<T> declaredConstructor = clazz.getDeclaredConstructor();//反射创建构造器
            declaredConstructor.setAccessible(true);//打破Private修饰限制
            T t = declaredConstructor.newInstance(); //创建代表一行数据的实体类T的对象

            //************到下面的*之间完成的是:将SQL语句获得的结果集的一行数据,对应着赋值给一个实体类对象的各个属性。
            for (int i = 1; i <= columnCount; i++) {//对结果集的一行进行列的遍历
                String columnLabel = metaData.getColumnLabel(i);//根据列的下标获取一行中对应的列名
                Object value = resultSet.getObject(i);//根据列的下标获取一行中对应列的值
                /*
                看下面之前你要明白:结果集 和 原表是两个表,我们是对结果集进行解析,不是原表
                                而我们在通过sql语句查询获取结果集时,可以给结果集的每一列重新起一个别名。
                                另外:你要会如何用反射创建类的对象,获得类的属性以及给属性赋值。

                利用反射,根据类的属性名获取类的属性,从而给上面创建的实体类对象t的属性赋值。
                那么怎么拿到类的属性名呢?
                如果类的属性名和ResultSet结果集的列名相等,那么我们就可以用结果集的列名充当类的属性名,那怎么保证它们两个相等呢?
                有两种方式:
                          方式1. 实体类T的属性名和对应原表的列名相同
                          方式2. 在执行SQL语句生成结果集的时候,把结果集的列名起一个别名,让别名和实体类的类名对应相等,那么我们
                          就实现了 类的属性名和ResultSet结果集的列名相等 这个条件。
                 */
                Field declaredField = clazz.getDeclaredField(columnLabel);//获得属性,根据属性名
                declaredField.setAccessible(true);//打破Private修饰限制
                declaredField.set(t,value);//给属性赋值
                //********************************
            }
            list.add(t);//在结果集的next()循环中,每next()一次就是一行数据,将这一行对应的实体类对象t添加到list集合中
        }
        if(connection.getAutoCommit()){//判断一下,是否需要在Dao层关闭关闭,即是否开启了手动提交事务。开启了就不关闭了,交给业务层关闭。
            DruidUtilsV2.CloseConnection();
        }
        return list;
    }
}


尚硅谷JDBC实战教程(2023最新版jdbc,JDK17+MySQL8)的评论 (共 条)

分享到微博请遵守国家法律