package com.atguigu.api.utils;标签:语句,jdbc,Utils,获取,connection,Jdbc,params,sql,属性 From: https://www.cnblogs.com/zhazhawei906/p/17125018.html
import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 封装Dao数据库重复代码
* TODO :
* 两个方法1.简化非DQL语句(非dql就是增删改)
* 2.简化DQL语句(查询语句)
* 3.Object ... params传入占位符的值必须和sql语句中的位置对应。
*/
public abstract class BaseDao {
/**
* sql 封装简化非DQL语句
* params 用于存放占位符的数据,可以有多个,可以当做数组使用,使用的时候遍历传入就行了
*/
public int executeUpdate1(String sql,Object ... params) throws SQLException {//params可以当做数组使用,把
//sql语句是要从外部传入的。但是获取连接是固定的。
Connection connection = Jdbc_Druid_Utils_V2.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement(sql);//这两布是必须的。
for (int i = 1; i <= params.length; i++) {
preparedStatement.setObject(i,params[(i-1)]);//给sql语句中的占位符进行赋值,第i个占位符就是第i个值
}
int rows = preparedStatement.executeUpdate();//执行这个sql语句,并获取影响的行数
//关闭资源
preparedStatement.close();
//如果开启事物的话就不对连接进行操作。如果没有开启事物的话就回收连接
if (connection.getAutoCommit()) {//如果connection.getAutoCommit()==true,表示事物为默认状态,需要回收
Jdbc_Druid_Utils_V2.freeConnection();
}
return rows;//因为是非查询语句,所以讲得到的影响的行数进行抛出
}
/**
* DQL获取的数据一般是存放在一个list<map>中,每一个map就是一行数据(id=1,acc=zxw,password=123)
*
* V2.0版本
* public <T> List <T> executeQuery(Class clazz,String sql,Object... params);
* 将获取到的数据也是存进一个集合中,不过在这个集合中存放的就不是map了,而是一个个对象,将数据库中的列名(id,account,password)
* 作为这个对象的属性,而对应的值设置为这个对象属性的值。最后将对象添加到list中
*
* @param <T> 声明的结果的类型
* @param clazz 要接收值的实体类集合的模板对象
* @param params 占位符的值要和?对应位置
* @param sql 查询语句,要求列名或者别名=实体类的属性名
* @return 查询的实体类的集合
* <T>声明一个泛型,一个不确定的泛型
* 1.确定泛型User.class T=User
* 2.要使用反射技术给属性赋值
*/
public <T> List<T> executeQuery(Class clazz, String sql, Object... params) throws SQLException, InstantiationException, IllegalAccessException, NoSuchFieldException {
//首先获取连接
Connection connection = Jdbc_Druid_Utils_V2.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement(sql);
//给传入sql语句的占位符进行赋值
if (params!=null && params.length!=0){
for (int i = 1; i <= params.length; i++) {
preparedStatement.setObject(i,params[(i-1)]);//给sql语句中的占位符进行赋值,第i个占位符就是第i个值
}
}
ResultSet resultSet = preparedStatement.executeQuery();//发送sql语句获取数据
List<T> list = new ArrayList<>();//创建集合用于存放对象数据
//获取列的信息
ResultSetMetaData metaData = resultSet.getMetaData();//Metadata中存放的是列的信息,包括列名,列的数据、、、、
int columnCount = metaData.getColumnCount();//columnCount获取列的个数,有了它以后就可以水平遍历数据,第一列(id)、第二列(account)、、、
while (resultSet.next()){//获取一行数据,第一行、第二行、、、
//县创建一个对象
T t = (T) clazz.newInstance();//调用传入这个类的无参构造函数实例化对象。
for (int i = 1; i <=columnCount ; i++) {//for循环,将每一列的数据取出
String columnLabelName = metaData.getColumnLabel(i);//获取第i列的名字作为要存入对象的属性名(id、account、password、、、)循环获取
Object value = resultSet.getObject(i);//在第resultSet.next()行获取第i列的数据作为上述属性名的值。
//反射,给对象的属性进行赋值
//创建一个属性,名字为获取到的列明
Field field = clazz.getDeclaredField(columnLabelName);
//将属性改为可以设置,打破private的修饰限制
field.setAccessible(true);
/**
* 参数一:要赋值的对象
* 参数二:具体的属性的值,id这个属性的123
*/
field.set(t,value);//通过获取到的列名创建一个属性,属性名=获取到的列名,再通过set方法,将属性添加到t这个对象中,同时把获取的列的值value赋值给这个创建的属性。
//一次循环创建一个属性名,读取一个列的值
//循环完成后,一个包含所有列名的属性的类对象就创建好了
}
list.add(t);//将这个对象放进list中
}
//关闭资源
resultSet.close();
preparedStatement.close();
if (connection.getAutoCommit()) {//如果connection.getAutoCommit()==true,表示事物为默认状态,需要回收
Jdbc_Druid_Utils_V2.freeConnection();
}
return list;
}
}