Java反射实现无Sql语句的DAO抽象类
明天全栈大作业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 要查询的实体类*/
public abstract class BaseDao{QueryRunner runner = new QueryRunner();Connection connection = JdbcUtils.getConnection();protected Class cls;/*** @return class的类名(不是全类名)*/private String getClassName(){String[] split = cls.getName().split("\\.");return split[split.length - 1];}@SneakyThrowspublic 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集合*/@SneakyThrowspublic List 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集合*/@SneakyThrowspublic List getAll(){String sql = "select * from retail." + getClassName();return runner.query(connection, sql, new BeanListHandler<>(cls));}/*** 根据 id 删除表项* @param id id* @return 是否删除成功*/@SneakyThrowspublic 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 参数异常*/@SneakyThrowspublic 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(",");elseplaceHolder.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 参数异常*/@SneakyThrowspublic 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 idif(i < fieldNum - 1)placeHolder.append(declaredFields[i].getName()).append("=?,");elseplaceHolder.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); // 这个属性是idreturn runner.update(connection, sql, paramArray) > 0;}/*** @return 最大的 id 值*/@SneakyThrowsprivate int getMaxId(){String sql = "select max(id) from retail." + getClassName();return runner.query(connection, sql, new ScalarHandler<>());}
}
欢迎大家的批评建议
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
