mybatis-plus - TableInfo
2020-02-17 16:03:27来源:博客园 阅读 ()
mybatis-plus - TableInfo
在前面 的 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())); }
原文链接:https://www.cnblogs.com/elvinle/p/12321678.html
如有疑问请与原作者联系
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- MyBatis中的$和#,用不好,准备走人! 2020-06-11
- SpringBoot 2.3 整合最新版 ShardingJdbc + Druid + MyBatis 2020-06-11
- 天哪!手动编写mybatis雏形竟然这么简单 2020-06-06
- MyBatis整合双数据源 2020-06-04
- MyBatis缓存特性详解 2020-06-03
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash