zoukankan      html  css  js  c++  java
  • mybatis-plus

    在前面 的 inject() 方法中, 调用了一个 TableInfoHelper.initTableInfo(builderAssistant, modelClass) 方法, 来获取 表信息: TableInfo

      /**
         * <p>
         * 实体类反射获取表信息【初始化】
         * <p>
         *
         * @param clazz 反射实体类
         * @return 数据库表反射信息
         */
        public synchronized static TableInfo initTableInfo(MapperBuilderAssistant builderAssistant, Class<?> clazz) {
            TableInfo tableInfo = TABLE_INFO_CACHE.get(clazz);
            if (tableInfo != null) {
                if (tableInfo.getConfigMark() == null && builderAssistant != null) {
                    tableInfo.setConfigMark(builderAssistant.getConfiguration());
                }
                return tableInfo;
            }
    
            /* 没有获取到缓存信息,则初始化 */
            tableInfo = new TableInfo();
            GlobalConfig globalConfig;
            if (null != builderAssistant) {
                tableInfo.setCurrentNamespace(builderAssistant.getCurrentNamespace());
                tableInfo.setConfigMark(builderAssistant.getConfiguration());
                tableInfo.setUnderCamel(builderAssistant.getConfiguration().isMapUnderscoreToCamelCase());
                globalConfig = GlobalConfigUtils.getGlobalConfig(builderAssistant.getConfiguration());
            } else {
                // 兼容测试场景
                globalConfig = GlobalConfigUtils.defaults();
            }
    
            /* 初始化表名相关 */
            initTableName(clazz, globalConfig, tableInfo);
    
            /* 初始化字段相关 */
            initTableFields(clazz, globalConfig, tableInfo);
    
            /* 放入缓存 */
            TABLE_INFO_CACHE.put(clazz, tableInfo);
    
            /* 缓存 Lambda 映射关系 */
            LambdaUtils.createCache(clazz, tableInfo);
            return tableInfo;
        }

    是不是还是自己人写的代码看起来爽? 这中文注释, 都不用看方法具体是干啥的. 

    这里的  TABLE_INFO_CACHE  是用来缓存表信息的:

    /**
     * 储存反射类表信息
     */
    private static final Map<Class<?>, TableInfo> TABLE_INFO_CACHE = new ConcurrentHashMap<>();

    第一次进这个方法的时候, 肯定是空的, 要去解析获取.

    1. initTableName()

     /**
         * <p>
         * 初始化 表数据库类型,表名,resultMap
         * </p>
         *
         * @param clazz        实体类
         * @param globalConfig 全局配置
         * @param tableInfo    数据库表反射信息
         */
        public static void initTableName(Class<?> clazz, GlobalConfig globalConfig, TableInfo tableInfo) {
            /* 数据库全局配置 */
            GlobalConfig.DbConfig dbConfig = globalConfig.getDbConfig();
            /* 设置数据库类型 */
            tableInfo.setDbType(dbConfig.getDbType());
    
            /* 设置表名 */
            TableName table = clazz.getAnnotation(TableName.class);
            String tableName = clazz.getSimpleName();
            if (table != null && StringUtils.isNotEmpty(table.value())) {
                tableName = table.value();
            } else {
                // 开启表名下划线申明
                if (dbConfig.isTableUnderline()) {
                    tableName = StringUtils.camelToUnderline(tableName);
                }
                // 大写命名判断
                if (dbConfig.isCapitalMode()) {
                    tableName = tableName.toUpperCase();
                } else {
                    // 首字母小写
                    tableName = StringUtils.firstToLowerCase(tableName);
                }
                // 存在表名前缀
                if (null != dbConfig.getTablePrefix()) {
                    tableName = dbConfig.getTablePrefix() + tableName;
                }
            }
            tableInfo.setTableName(tableName);
    
            /* 表结果集映射 */
            if (table != null && StringUtils.isNotEmpty(table.resultMap())) {
                tableInfo.setResultMap(table.resultMap());
            }
    
            /* 开启了自定义 KEY 生成器 */
            if (null != dbConfig.getKeyGenerator()) {
                tableInfo.setKeySequence(clazz.getAnnotation(KeySequence.class));
            }
        }

    判断逻辑:

    1. 判断实体类上面有没有 TableName 注解

      |-> 如果有, 则拿注解里面配置的 value 作为表名

      |-> 如果没有, 则根据类名进行解析

    2. initTableFields()

      /**
         * <p>
         * 初始化 表主键,表字段
         * </p>
         *
         * @param clazz        实体类
         * @param globalConfig 全局配置
         * @param tableInfo    数据库表反射信息
         */
        public static void initTableFields(Class<?> clazz, GlobalConfig globalConfig, TableInfo tableInfo) {
            /* 数据库全局配置 */
            GlobalConfig.DbConfig dbConfig = globalConfig.getDbConfig();
            List<Field> list = getAllFields(clazz);
            // 标记是否读取到主键
            boolean isReadPK = false;
            // 是否存在 @TableId 注解
            boolean existTableId = isExistTableId(list);
    
            List<TableFieldInfo> fieldList = new ArrayList<>();
            for (Field field : list) {
                /*
                 * 主键ID 初始化
                 */
                if (!isReadPK) {
                    if (existTableId) {
                        isReadPK = initTableIdWithAnnotation(dbConfig, tableInfo, field, clazz);
                    } else {
                        isReadPK = initTableIdWithoutAnnotation(dbConfig, tableInfo, field, clazz);
                    }
                    if (isReadPK) {
                        continue;
                    }
                }
                /* 有 @TableField 注解的字段初始化 */
                if (initTableFieldWithAnnotation(dbConfig, tableInfo, fieldList, field, clazz)) {
                    continue;
                }
    
                /* 无 @TableField 注解的字段初始化 */
                fieldList.add(new TableFieldInfo(dbConfig, tableInfo, field));
            }
    
            /* 检查逻辑删除字段只能有最多一个 */
            Assert.isTrue(fieldList.parallelStream().filter(TableFieldInfo::isLogicDelete).count() < 2L,
                String.format("annotation of @TableLogic can't more than one in class : %s.", clazz.getName()));
    
            /* 字段列表 */
            tableInfo.setFieldList(fieldList);
    
            /* 未发现主键注解,提示警告信息 */
            if (StringUtils.isEmpty(tableInfo.getKeyColumn())) {
                logger.warn(String.format("Warn: Could not find @TableId in Class: %s.", clazz.getName()));
            }
        }

    2.1 getAllFields()

        /**
         * 获取该类的所有属性列表
         *
         * @param clazz 反射类
         * @return 属性集合
         */
        public static List<Field> getAllFields(Class<?> clazz) {
            List<Field> fieldList = ReflectionKit.getFieldList(ClassUtils.getUserClass(clazz));
            if (CollectionUtils.isNotEmpty(fieldList)) {
                return fieldList.stream()
                    .filter(i -> {
                        /* 过滤注解非表字段属性 */
                        TableField tableField = i.getAnnotation(TableField.class);
                        return (tableField == null || tableField.exist());
                    }).collect(toList());
            }
            return fieldList;
        }

    如果字段上面加了 TableField 注解, 如果有则进行特殊处理. 如果配置了 exist=false, 则这个字段, 过滤掉, 不参与sql生成.

    2.2 initTableIdWithAnnotation()

    如果实体类中有 TableId 注解, 则进入此方法, 一般情况下, 最好是配一下 TableId

        /**
         * <p>
         * 主键属性初始化
         * </p>
         *
         * @param dbConfig  全局配置信息
         * @param tableInfo 表信息
         * @param field     字段
         * @param clazz     实体类
         * @return true 继续下一个属性判断,返回 continue;
         */
        private static boolean initTableIdWithAnnotation(GlobalConfig.DbConfig dbConfig, TableInfo tableInfo,
                                                         Field field, Class<?> clazz) {
            TableId tableId = field.getAnnotation(TableId.class);
            boolean underCamel = tableInfo.isUnderCamel();
            if (tableId != null) {
                if (StringUtils.isEmpty(tableInfo.getKeyColumn())) {
                    /* 主键策略( 注解 > 全局 ) */
                    // 设置 Sequence 其他策略无效
                    if (IdType.NONE == tableId.type()) {
                        tableInfo.setIdType(dbConfig.getIdType());
                    } else {
                        tableInfo.setIdType(tableId.type());
                    }
    
                    /* 字段 */
                    String column = field.getName();
                    if (StringUtils.isNotEmpty(tableId.value())) {
                        column = tableId.value();
                    } else {
                        // 开启字段下划线申明
                        if (underCamel) {
                            column = StringUtils.camelToUnderline(column);
                        }
                        // 全局大写命名
                        if (dbConfig.isCapitalMode()) {
                            column = column.toUpperCase();
                        }
                    }
                    tableInfo.setKeyRelated(checkRelated(underCamel, field.getName(), column))
                        .setClazz(field.getDeclaringClass())
                        .setKeyColumn(column)
                        .setKeyProperty(field.getName());
                    return true;
                } else {
                    throwExceptionId(clazz);
                }
            }
            return false;
        }

    2.3 initTableFieldWithAnnotation()

    这里对 TableField 进行解析赋值. 如  value 解析成 字段名称

        /**
         * <p>
         * 字段属性初始化
         * </p>
         *
         * @param dbConfig  数据库全局配置
         * @param tableInfo 表信息
         * @param fieldList 字段列表
         * @param clazz     当前表对象类
         * @return true 继续下一个属性判断,返回 continue;
         */
        private static boolean initTableFieldWithAnnotation(GlobalConfig.DbConfig dbConfig, TableInfo tableInfo,
                                                            List<TableFieldInfo> fieldList, Field field, Class<?> clazz) {
            /* 获取注解属性,自定义字段 */
            TableField tableField = field.getAnnotation(TableField.class);
            if (null == tableField) {
                return false;
            }
            String columnName = field.getName();
            if (StringUtils.isNotEmpty(tableField.value())) {
                columnName = tableField.value();
            }
            /*
             * el 语法支持,可以传入多个参数以逗号分开
             */
            String el = field.getName();
            if (StringUtils.isNotEmpty(tableField.el())) {
                el = tableField.el();
            }
            String[] columns = columnName.split(StringPool.SEMICOLON);
            String[] els = el.split(StringPool.SEMICOLON);
            if (columns.length == els.length) {
                for (int i = 0; i < columns.length; i++) {
                    fieldList.add(new TableFieldInfo(dbConfig, tableInfo, field, columns[i], els[i], tableField));
                }
                return true;
            }
            throw ExceptionUtils.mpe(String.format("Class: %s, Field: %s, 'value' 'el' Length must be consistent.",
                clazz.getName(), field.getName()));
        }
  • 相关阅读:
    Linux命令大全之关机重启命令
    Linux命令大全之帮助命令及压缩命令
    Linux命令大全之搜索命令
    Linux命令大全之基本命令
    Linux安装界面简介
    Linux 的ftp服务未启用怎么办
    创建分区表
    Linux分区,格式化概念理解
    VMware简介
    Linux简介
  • 原文地址:https://www.cnblogs.com/elvinle/p/12321678.html
Copyright © 2011-2022 走看看