package com.atguigu.myssm.baseDAO;
import com.atguigu.myssm.util.DateUtil;
import com.atguigu.myssm.util.MyTypeUtil;
import java.lang.reflect.*;
import java.sql.*;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
/**
* @author e_n
* @version 1.0.0
* @ClassName BaseDAO.java
* @Description 优化后的BaseDAO,可以利用泛型进行通用化,简化内方法的调用
* @CreateTime 2022/01/30 16:13
*/
public abstract class BaseDAO<T> {
private Class<T> clazz = null;
private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// 在代码块中对clazz进行赋值,当前对象的父类的泛型
{
// this是该类的实例对象
Type genericSuperclass = this.getClass().getGenericSuperclass();
ParameterizedType paramType = (ParameterizedType) genericSuperclass;
Type[] typeArguments = paramType.getActualTypeArguments();
clazz = (Class<T>) typeArguments[0];
}
/**
* @title update
* @Description 增删改通用方法
* @author e_n
* @param conn
* @param sql
* @param args
* @return int
* @throws
* @CreateTime 2022/2/2 22:13
*/
public int update(Connection conn, String sql, Object...args) {
PreparedStatement ps = null;
try {
// 1.sql预编译
ps = conn.prepareStatement(sql);
// 2.填充占位符
for (int i = 0; i < args.length; i++) {
ps.setObject(i+1,args[i]);
}
// 3.执行sql
return ps.executeUpdate();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return 0;
}
/**
* @title CommonRetrieve
* @Description 返回多条记录的通用查询方法
* @author e_n
* @param conn
* @param sql
* @param args
* @return java.util.List<T>
* @throws
* @CreateTime 2022/2/2 22:13
*/
public List<T> CommonRetrieve(Connection conn, String sql, Object...args) {
PreparedStatement ps = null;
ResultSet rs = null;
try {
// 1.预编译sql,生成PreparedStatement对象
ps = conn.prepareStatement(sql);
// 2.填充占位符
for (int i = 0; i < args.length; i++) {
ps.setObject(i+1,args[i]);
}
// 3.执行并返回结果集
rs = ps.executeQuery();
// 4.处理结果集
// 4.1 创建该结果集的元数据,通过元数据获取结果集中数据的信息
ResultSetMetaData rsmd = rs.getMetaData();
// 4.2 获取结果集中列的个数
int columnCount = rsmd.getColumnCount();
// 4.3 创建用于存储结果集中多条记录的集合
ArrayList<T> tSet = new ArrayList<>();
while (rs.next()) {
// 4.4 处理该行记录的每一个字段
// 4.4.1 创建该行记录在JavaBean中类的对象,此处用泛型实现
T t = clazz.newInstance();
// 4.4.2 利用通过元素据获得的结果集中列的个数,结合for循环对结果集中的列进行遍历
for (int i = 0; i < columnCount; i++) {
// 4.4.3 通过结果集对象获取该字段的值
Object columnValue = rs.getObject(i + 1);
// 4.4.4 通过元素据获取该字段的别(列)名,该列名与该行记录对应的对象中的属性名相同
String columnLabel = rsmd.getColumnLabel(i+1);
// 4.4.5 通过反射,给Customers对象中对应的属性赋值,实现将结果集中的数据存储到对象中
Field field = clazz.getDeclaredField(columnLabel);
// 4.4.6 如果属性是自定义类型,则需要将带有一个指定参数的自定义类的实例对象赋值给该对象
String typeName = field.getType().getName();
// 1.判断该字段对应属性类型是否为Date类型
if (DateUtil.isDateTime(typeName)) {
// 2.再次使用结果集rs,直接获取为Timestamp时间类型
Timestamp timestamp = rs.getTimestamp(i+1);
// 3.使用SimpleDateFormat,将其格式化为字符串
String format1 = format.format(timestamp.getTime());
System.out.println("format1 = " + format1);
// 4.再将该字符串解析为java.util.Date类型,最后赋值给columnValue
columnValue = format.parse(format1);
System.out.println("columnValue = " + columnValue.toString());
}
if (MyTypeUtil.isMyType(typeName)){
// 获取该自建类的运行时类
Class typeNameClass = Class.forName(typeName);
// 利用反射获取其构造器
Constructor constructor = typeNameClass.getDeclaredConstructor(Integer.class);
columnValue = constructor.newInstance(columnValue);
}
// 确保私有属性可以访问
field.setAccessible(true);
// 给该字段对应的属性赋值
field.set(t,columnValue);
}
// 4.4.6 将此次循环产生的对象加入新建的集合中
tSet.add(t);
}
return tSet;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* @title singleCommonRetrieve
* @Description 返回单条记录的通用查询方法
* @author e_n
* @param conn
* @param sql
* @param args
* @return T
* @throws
* @CreateTime 2022/2/2 22:14
*/
public T singleCommonRetrieve(Connection conn, String sql, Object...args) {
PreparedStatement ps = null;
ResultSet rs = null;
try {
// 1.预编译sql,生成PreparedStatement对象
ps = conn.prepareStatement(sql);
// 2.填充占位符
for (int i = 0; i < args.length; i++) {
ps.setObject(i+1,args[i]);
}
// 3.执行并返回结果集
rs = ps.executeQuery();
// 4.处理结果集
// 4.1 创建该结果集的元数据,通过元数据获取结果集中数据的信息
ResultSetMetaData rsmd = rs.getMetaData();
// 4.2 获取结果集中列的个数
int columnCount = rsmd.getColumnCount();
if (rs.next()) {
// 4.3 处理该行记录的每一个字段
// 4.3.1 创建该行记录在JavaBean中类的对象,此处用泛型实现
T t = clazz.newInstance();
// 4.3.2 利用通过元素据获得的结果集中列的个数,结合for循环对结果集中的列进行遍历
for (int i = 0; i < columnCount; i++) {
// 4.3.3 通过结果集对象获取该字段的值
Object columnValue = rs.getObject(i + 1);
// 4.3.4 通过元素据获取该字段的别(列)名,该列名与该行记录对应的对象中的属性名相同
String columnLabel = rsmd.getColumnLabel(i+1);
// 4.3.5 通过反射,给Customers对象中对应的属性赋值,实现将结果集中的数据存储到对象中
Field field = clazz.getDeclaredField(columnLabel);
// 4.4.6 如果属性是自定义类型,则需要将带有一个指定参数的自定义类的实例对象赋值给该对象
String typeName = field.getType().getName();
评论0