• 按照Mybatis的反射和自动代理,使用JDBC进行模拟


    package com.csy.dao;
    
    
    import com.csy.config.ConfigMng;
    
    import java.lang.reflect.Field;
    import java.lang.reflect.InvocationTargetException;
    import java.sql.*;
    import java.time.LocalDateTime;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    /**
     * @Description: 管理数据库的连接与释放
     * @Author: windStop
     * @Date: 2024/5/20 16:38
     */
    public class BaseDao {
        public Connection connection = null;
        public PreparedStatement pStatement = null;
        public ResultSet resultSet = null;
    
    
        //使用配置文件的方式进行解耦合,可以在无需重新编译的基础上进行修改内容
        public boolean getConnection() {
            try {
                ConfigMng configMng = ConfigMng.getInstance();
                Class.forName(configMng.getString("jdbc.driver"));
                String url = configMng.getString("jdbc.url");
                connection = DriverManager.getConnection(url, configMng.getString("jdbc.username"), configMng.getString("jdbc.password"));
            }
            catch (Exception e) {
                e.printStackTrace();
                return false;
            }
            return true;
        }
    
        public boolean closeResource() {
            try {
                if (resultSet != null)
                    resultSet.close();
                if (pStatement != null)
                    pStatement.close();
                if (connection != null)
                    connection.close();
            } catch (SQLException e) {
                e.printStackTrace();//把异常信息打印在控制台中
                return false;
            }
            return true;
        }
    
        /**
         * 封装增删改操作
         * @param sql sql语句
         * @param params 参数占位符 ?的填充的内容
         * @return 影响了多少条数据
         */
        public int executeUpdate(String sql, Object[] params) {
            if (getConnection()) {
                //1.执行sql语句
                try {
                    pStatement = connection.prepareStatement(sql);
                    //2.填充占位符
                    for (int i = 0; i < params.length; i++) {
                        pStatement.setObject(i + 1,params[i]);
                    }
                    return pStatement.executeUpdate();
                } catch (SQLException e) {
                    throw new RuntimeException(e);
                }finally {
                    closeResource();
                }
            }
            return 0;
        }
    
        /**
         * 通过拆解出where条件后面跟的条件,然后遍历javabean的属性找到相应的进行插入。最后将结果ResultSet映射到javabean中返回
         * @param sql sql语句
         * @param obj 调用者传来的javabean
         * @return 查询到的javabean集合
         * @param  javabean的泛型
         */
        public   List executeQuery(String sql, T obj) throws IllegalAccessException, SQLException {
            List resultList = new ArrayList<>();
            if (getConnection()) {
                pStatement = connection.prepareStatement(sql);
                // 使用反射获取对象的属性值
                Class clazz = obj.getClass();
                //获取该对象中的所有属性(包括私有)所有字段
                Field[] fields = clazz.getDeclaredFields();
    
                List conditionFields = extractConditionFields(sql);
    
                for (int i = 0; i < conditionFields.size(); i++) {
                    // 填充占位符内容
                    for (Field field : fields) {
                        //私有暴力反射 设置可访问私有字段
                        field.setAccessible(true);
                        if (field.getName().equals(conditionFields.get(i))){//找到相等的了
                            //接受一个对象实例作为参数,返回该对象实例中对应字段的值。
                            Object value = field.get(obj);
                            pStatement.setObject(i + 1,value);
                            break;
                        }
                    }
                }
                resultSet = pStatement.executeQuery();
                    while (resultSet.next()) {
                        // 根据泛型类型创建对象并填充数据
                        T resultObj = (T)createObjectFromResultSet(resultSet, clazz);
                        resultList.add(resultObj);
                    }
                }
            return resultList;
        }
    
        //将resultSet的返回值封装到泛型对象中,并且返回(这里我没有处理表名映射下划线和驼峰)
        private  T createObjectFromResultSet(ResultSet resultSet, Class clazz) throws SQLException {
            T obj;
            try {
                obj = clazz.getDeclaredConstructor().newInstance();
                Field[] fields = clazz.getDeclaredFields();
                for (Field field : fields) {
                    field.setAccessible(true);
                    String fieldName = field.getName();
                    Class fieldType = field.getType();
    
                    // 根据字段类型从结果集中获取相应的值
                    if (fieldType == String.class) {
                        String value = resultSet.getString(fieldName);
                        field.set(obj, value);
                    } else if (fieldType == Integer.class || fieldType == int.class) {
                        int value = resultSet.getInt(fieldName);
                        field.set(obj, value);
                    } else if (fieldType == Date.class) {
                        Date value = resultSet.getDate(fieldName);
                        field.set(obj, value);
                    } else if (fieldType == LocalDateTime.class) {
                        Timestamp timestamp = resultSet.getTimestamp(fieldName);
                        LocalDateTime value = timestamp.toLocalDateTime();
                        field.set(obj, value);
                    } else {
                        // 其他类型的处理... 想到在写
                    }
                }
            } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
                throw new SQLException("Error creating object from ResultSet", e);
            }
            return obj;
        }
    
        //截取出where条件中的所有字段条件的名称
        public List extractConditionFields(String sql) {
            List conditionFields = new ArrayList<>();
    
            // 使用正则表达式匹配 WHERE 子句
            Pattern wherePattern = Pattern.compile("where(.*)", Pattern.CASE_INSENSITIVE);
            Matcher whereMatcher = wherePattern.matcher(sql);
    
            if (whereMatcher.find()) {
                String whereClause = whereMatcher.group(1).trim();
    
                // 使用正则表达式匹配条件字段
                Pattern conditionPattern = Pattern.compile("(\\w+)\\s?=\\s?");
                Matcher conditionMatcher = Pattern.compile("and", Pattern.CASE_INSENSITIVE).matcher(whereClause);
    
                int lastIndex = 0;
                while (conditionMatcher.find()) {
                    String condition = whereClause.substring(lastIndex, conditionMatcher.start()).trim();
                    Matcher fieldMatcher = conditionPattern.matcher(condition);
                    if (fieldMatcher.find()) {
                        conditionFields.add(fieldMatcher.group(1));
                    }
                    lastIndex = conditionMatcher.end();
                }
    
                // 处理最后一个条件
                String lastCondition = whereClause.substring(lastIndex).trim();
                Matcher lastFieldMatcher = conditionPattern.matcher(lastCondition);
                if (lastFieldMatcher.find()) {
                    conditionFields.add(lastFieldMatcher.group(1));
                }
            }
    
            return conditionFields;
        }
    
    
    
    
    }
    
    
  • 相关阅读:
    【StreamSets 】重置管道状态——管道的数据记忆
    C++中的双端队列(deque)
    关于印发《深圳市福田区支持战略性新兴产业和未来产业集群发展若干措施》的通知
    【Java并发编程一】并发与并行
    C++ 输入N本书,查找并且显示书相关信息
    jmeter-9-断言之JsonSchema(超推荐)
    一招教会你配置Jenkins钉钉消息通知
    word导出或另存为pdf图片不清晰问题解决方案
    Xcode15+iOS17适配以及遇到的问题
    mysql不是内部或外部命令,也不是可运行的程序或批处理文件解决
  • 原文地址:https://blog.csdn.net/m0_74749208/article/details/139236269