明天全栈大作业ddl就要截止了, 晚上我本想再认真检查一遍业务的,但是我看这些相似度80%的XxxDao是在看不顺眼, 于是突发奇想,写了一套完全脱离Sql语句使用的增删查改操作(主要使用了反射, 感觉就是在玩高难度的字符串拼接游戏)
因为只是大作业, 所以用了比较古老的JavaEE,没有上手框架
package dao;
import lombok.SneakyThrows;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import utils.JdbcUtils;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.util.List;
import java.util.Locale;
/**
* author Xiao
* @param <T> 要查询的实体类
*/
public abstract class BaseDao<T>{
QueryRunner runner = new QueryRunner();
Connection connection = JdbcUtils.getConnection();
protected Class<T> cls;
/**
* @return class的类名(不是全类名)
*/
private String getClassName(){
String[] split = cls.getName().split("\\.");
return split[split.length - 1];
}
@SneakyThrows
public T getById(int id){
String sql = "select * from " + getClassName() +" where id=?";
return runner.query(connection, sql, new BeanHandler<>(cls), id);
}
/**
* 根据 name 查询结果
* @param pattern 可以匹配的字符串
* @return 查询结果List集合
*/
@SneakyThrows
public List<T> getByName(String pattern){
String sql;
String name;
switch(cls.getName()){
case "User":{
name = "username";
break;
}
case "RepoInfo":{
name = "goodsName";
break;
}
default:{
name = "name";
}
}
sql = "select * from retail." + getClassName() + " where " + name + " like ? ";
return runner.query(connection, sql, new BeanListHandler<>(cls), "%" + pattern + "%");
}
/**
* @return 所有对象的List集合
*/
@SneakyThrows
public List<T> getAll(){
String sql = "select * from retail." + getClassName();
return runner.query(connection, sql, new BeanListHandler<>(cls));
}
/**
* 根据 id 删除表项
* @param id id
* @return 是否删除成功
*/
@SneakyThrows
public boolean deleteById(int id){
String sql = "delete from retail." + getClassName() + " where id=?";
return runner.update(connection, sql, id) > 0;
}
/**
* 插入一条记录
* @param t 实体类对象
* @return 是否插入成功
* @throws NoSuchMethodException 找不到方法
* @throws InvocationTargetException 方法作用的对象不正确
* @throws IllegalAccessException 参数异常
*/
@SneakyThrows
public boolean insert(T t) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException{
Field[] declaredFields = this.cls.getDeclaredFields(); // 所有的属性
int fieldNum = declaredFields.length; // 属性的数量
StringBuilder placeHolder = new StringBuilder();
placeHolder.append("(");
for(int i = 0; i < fieldNum; i++){
if(i < fieldNum - 1)
placeHolder.append("?").append(",");
else
placeHolder.append("?");
}
placeHolder.append(")");
String sql = "insert into retail.Goods values" + placeHolder;
int maxId = getMaxId();
Object[] paramArray = new Object[fieldNum];
// 方法对象
paramArray[0] = maxId + 1;
for(int i = 1; i < fieldNum; i++){ // 从1开始因为id不需要设置
String filedName = declaredFields[i].getName(); // 属性名
String methodName = "get" + filedName.substring(0, 1).toUpperCase(Locale.ROOT) + filedName.substring(1);
// 合成get属性的方法名
Method method = this.cls.getDeclaredMethod(methodName);
// 方法对象
paramArray[i] = method.invoke(t);
}
return runner.update(connection, sql, paramArray) > 0;
}
/**
* 根据 id 修改一条记录
* @param t 实体类对象
* @return 是否修改成功
* @throws NoSuchMethodException 找不到方法
* @throws InvocationTargetException 方法作用的对象不正确
* @throws IllegalAccessException 参数异常
*/
@SneakyThrows
public boolean updateById(T t) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException{
Field[] declaredFields = this.cls.getDeclaredFields(); // 所有的属性
int fieldNum = declaredFields.length; // 属性的数量
StringBuilder placeHolder = new StringBuilder();
placeHolder.append(" set ");
for(int i = 1; i < fieldNum; i++){ // 从1开始, 因为不用set id
if(i < fieldNum - 1)
placeHolder.append(declaredFields[i].getName()).append("=?,");
else
placeHolder.append(declaredFields[i].getName()).append("=?"); // 最后一句set不要逗号
}
String sql = "update retail." + getClassName() + placeHolder + " where id=?";
Object[] paramArray = new Object[fieldNum];
// 方法对象
for(int i = 1; i < fieldNum; i++){ // 从1开始, 因为id是最后一个参数
String filedName = declaredFields[i].getName(); // 属性名
String methodName = "get" + filedName.substring(0, 1).toUpperCase(Locale.ROOT) + filedName.substring(1);
// 合成get属性的方法名
Method method = this.cls.getDeclaredMethod(methodName);
// 方法对象
paramArray[i - 1] = method.invoke(t);
}
Method method = this.cls.getDeclaredMethod("getId");
paramArray[fieldNum - 1] = method.invoke(t); // 这个属性是id
return runner.update(connection, sql, paramArray) > 0;
}
/**
* @return 最大的 id 值
*/
@SneakyThrows
private int getMaxId(){
String sql = "select max(id) from retail." + getClassName();
return runner.query(connection, sql, new ScalarHandler<>());
}
}
欢迎大家的批评建议