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;
}
}
标签: