diff --git a/docs/zh/others/apt.md b/docs/zh/others/apt.md index 7793a08b..3b9af366 100644 --- a/docs/zh/others/apt.md +++ b/docs/zh/others/apt.md @@ -26,16 +26,35 @@ MyBatis-Flex 使用了 APT(Annotation Processing Tool)技术,在项目编 | processor.mapper.annotation | 开启 @Mapper 注解 | true/false | false | | processor.mapper.baseClass | 自定义 Mapper 的父类 | 全路径类名 | com.mybatisflex.core.BaseMapper | | processor.mapper.package | 自定义 Mapper 生成的包名 | 合法的包名 | ${entityPackage}.mapper | +| processor.tableDef.package | 生成辅助类的包名 | 合法的包名 | ${entityPackage}.table | | processor.tableDef.propertiesNameStyle | 生成辅助类的字段风格 | upperCase, lowerCase
upperCamelCase, lowerCamelCase | upperCase | | processor.tableDef.instanceSuffix | 生成的表对应的变量后缀 | string | 空字符串 | | processor.tableDef.classSuffix | 生成的 TableDef 类的后缀 | string | TableDef | | processor.tableDef.ignoreEntitySuffixes | 过滤 Entity 后缀 | string | - | +对于示例中的包名表达式,说明如下: + +1. 仅支持以下配置项使用表达式 + ```text + processor.allInTables.package + processor.mapper.package + processor.tableDef.package + ``` +2. `${entityPackage}`: 表示 Entity 类所在的包名 +3. `${entityPackage.parent}`: 表示 Entity 类所在的上一级包名 +4. `parent` 参数的数量没有限制,但如果超出了可能的层级,则会导致异常 **示例配置:** 假设 Example 类的全限定类名为 `com.mybatisflex.entity.Example` +配置内容如下: + +```properties +processor.allInTables.package=${entityPackage}.table +processor.mapper.package=${entityPackage.parent}.mapper +processor.tableDef.package=${entityPackage.parent.parent}.table +``` 生成类的全限定类名如下: diff --git a/mybatis-flex-processor/src/main/java/com/mybatisflex/processor/MybatisFlexProcessor.java b/mybatis-flex-processor/src/main/java/com/mybatisflex/processor/MybatisFlexProcessor.java index ddb0c540..2b71e3bc 100644 --- a/mybatis-flex-processor/src/main/java/com/mybatisflex/processor/MybatisFlexProcessor.java +++ b/mybatis-flex-processor/src/main/java/com/mybatisflex/processor/MybatisFlexProcessor.java @@ -125,6 +125,7 @@ public class MybatisFlexProcessor extends AbstractProcessor { String mapperBaseClass = configuration.get(ConfigurationKey.MAPPER_BASE_CLASS); // tableDef 配置 + String tableDefPackage = configuration.get(ConfigurationKey.TABLE_DEF_PACKAGE); String tableDefClassSuffix = configuration.get(ConfigurationKey.TABLE_DEF_CLASS_SUFFIX); String tableDefInstanceSuffix = configuration.get(ConfigurationKey.TABLE_DEF_INSTANCE_SUFFIX); String tableDefPropertiesNameStyle = configuration.get(ConfigurationKey.TABLE_DEF_PROPERTIES_NAME_STYLE); @@ -180,23 +181,23 @@ public class MybatisFlexProcessor extends AbstractProcessor { tableInfo.setEntityComment(elementUtils.getDocComment(entityClassElement)); // 生成 TableDef 文件 - String tableDefPackage = StrUtil.buildTableDefPackage(entityClass); + String realTableDefPackage = StrUtil.isBlank(tableDefPackage) ? StrUtil.buildTableDefPackage(entityClass) : StrUtil.processPackageExpression(entityClass, tableDefPackage); String tableDefClassName = entityClassName.concat(tableDefClassSuffix); - String tableDefContent = ContentBuilder.buildTableDef(tableInfo, allInTablesEnable, tableDefPackage, tableDefClassName + String tableDefContent = ContentBuilder.buildTableDef(tableInfo, allInTablesEnable, realTableDefPackage, tableDefClassName , tableDefPropertiesNameStyle, tableDefInstanceSuffix, columnInfos, defaultColumns); // 将文件所依赖的 Element 传入 Filer 中,表示此 TableDef 依赖这个类,以保证增量编译时不丢失内容。 - processGenClass(genPath, tableDefPackage, tableDefClassName, tableDefContent, entityClassElement); + processGenClass(genPath, realTableDefPackage, tableDefClassName, tableDefContent, entityClassElement); if (allInTablesEnable) { // 标记 entity 类,如果没有配置 Tables 生成位置,以 entity 位置为准 entityClassReference = entityClass; // 构建 Tables 常量属性及其导包 - ContentBuilder.buildTablesField(importBuilder, fieldBuilder, tableInfo, tableDefClassSuffix, tableDefPropertiesNameStyle, tableDefInstanceSuffix); + ContentBuilder.buildTablesField(importBuilder, fieldBuilder, tableInfo, tableDefClassSuffix, tableDefPropertiesNameStyle, tableDefInstanceSuffix, realTableDefPackage); } // 是否生成 Mapper 文件 if ("true".equalsIgnoreCase(mapperGenerateEnable) && table.mapperGenerateEnable()) { - String realMapperPackage = StrUtil.isBlank(mapperPackage) ? StrUtil.buildMapperPackage(entityClass) : mapperPackage; + String realMapperPackage = StrUtil.isBlank(mapperPackage) ? StrUtil.buildMapperPackage(entityClass) : StrUtil.processPackageExpression(entityClass, mapperPackage); String mapperClassName = entityClassName.concat("Mapper"); boolean mapperAnnotationEnable = "true".equalsIgnoreCase(mapperAnnotation); String mapperClassContent = ContentBuilder.buildMapper(tableInfo, realMapperPackage, mapperClassName, mapperBaseClass, mapperAnnotationEnable); @@ -207,7 +208,7 @@ public class MybatisFlexProcessor extends AbstractProcessor { // 确定了要生成 Tables 类,且拥有至少一个被 Table 注解的类时再生成 Tables 类。 if (allInTablesEnable && entityClassReference != null) { // 生成 Tables 文件 - String realTablesPackage = StrUtil.isBlank(allInTablesPackage) ? StrUtil.buildTableDefPackage(entityClassReference) : allInTablesPackage; + String realTablesPackage = StrUtil.isBlank(allInTablesPackage) ? StrUtil.buildTableDefPackage(entityClassReference) : StrUtil.processPackageExpression(entityClassReference, allInTablesPackage); String realTablesClassName = StrUtil.isBlank(allInTablesClassName) ? "Tables" : allInTablesClassName; String tablesContent = ContentBuilder.buildTables(importBuilder, fieldBuilder, realTablesPackage, allInTablesClassName); processGenClass(genPath, realTablesPackage, realTablesClassName, tablesContent, elementsAnnotatedWith.toArray(new Element[0])); diff --git a/mybatis-flex-processor/src/main/java/com/mybatisflex/processor/builder/ContentBuilder.java b/mybatis-flex-processor/src/main/java/com/mybatisflex/processor/builder/ContentBuilder.java index fa699f2b..8609b92a 100644 --- a/mybatis-flex-processor/src/main/java/com/mybatisflex/processor/builder/ContentBuilder.java +++ b/mybatis-flex-processor/src/main/java/com/mybatisflex/processor/builder/ContentBuilder.java @@ -168,8 +168,7 @@ public class ContentBuilder { * 构建 Tables 文件常量属性。 */ public static void buildTablesField(StringBuilder importBuilder, StringBuilder fieldBuilder, TableInfo tableInfo, - String tableDefClassSuffix, String tableDefPropertiesNameStyle, String tableDefInstanceSuffix) { - String tableDefPackage = StrUtil.buildTableDefPackage(tableInfo.getEntityName()); + String tableDefClassSuffix, String tableDefPropertiesNameStyle, String tableDefInstanceSuffix, String tableDefPackage) { String tableDefClassName = tableInfo.getEntitySimpleName().concat(tableDefClassSuffix); importBuilder.append("import ").append(tableDefPackage).append('.').append(tableDefClassName).append(";\n"); String entityComment = tableInfo.getEntityComment(); diff --git a/mybatis-flex-processor/src/main/java/com/mybatisflex/processor/config/ConfigurationKey.java b/mybatis-flex-processor/src/main/java/com/mybatisflex/processor/config/ConfigurationKey.java index 86b951cd..97ca8518 100644 --- a/mybatis-flex-processor/src/main/java/com/mybatisflex/processor/config/ConfigurationKey.java +++ b/mybatis-flex-processor/src/main/java/com/mybatisflex/processor/config/ConfigurationKey.java @@ -77,6 +77,11 @@ public enum ConfigurationKey { MAPPER_PACKAGE("processor.mapper.package", null), + /** + * 自定义 Class 生成的包名。 + */ + TABLE_DEF_PACKAGE("processor.tableDef.package", null), + /** * 生成的 Class 的后缀。 */ diff --git a/mybatis-flex-processor/src/main/java/com/mybatisflex/processor/util/StrUtil.java b/mybatis-flex-processor/src/main/java/com/mybatisflex/processor/util/StrUtil.java index 5fc7ade0..0a8a082f 100644 --- a/mybatis-flex-processor/src/main/java/com/mybatisflex/processor/util/StrUtil.java +++ b/mybatis-flex-processor/src/main/java/com/mybatisflex/processor/util/StrUtil.java @@ -16,6 +16,11 @@ package com.mybatisflex.processor.util; +import java.util.Arrays; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + /** * 字符串工具类。 * @@ -28,6 +33,8 @@ public class StrUtil { private StrUtil() { } + private static final Pattern PACKAGE_REGEX = Pattern.compile("(?\\$\\{entityPackage[.parent]*\\})(?.*)"); + /** * com.mybatisflex.test.entity.Account -> Account */ @@ -114,6 +121,40 @@ public class StrUtil { } } + /** + * 解析包名表达式 + *

将{@code `${entityPackage}`}替换为实际实体包名, 表达式中如果存在一个{@code `.parent`}则缩减包名末尾的一位。

+ *

示例:{@code `entityClass = com.test1.test2`}
+ * 1. 对于{@code `packageStr = ${entityPackage}`}处理结果为 {@code `com.test1.test2`}
+ * 2. 对于{@code `packageStr = ${entityPackage.parent}`}处理结果为 {@code `com.test1`}
+ * 3. 对于{@code `packageStr = ${entityPackage.parent}.customize`}处理结果为 {@code `com.test1.customize`} + *

+ */ + public static String processPackageExpression(String entityClass, String packageStr) { + String entityPackage = entityClass.substring(0, entityClass.lastIndexOf(".")); + Matcher matcher = PACKAGE_REGEX.matcher(packageStr); + if (!matcher.find()) { + return packageStr; + } + String expression = matcher.group("expression"); + expression = expression.substring(2, expression.length() - 1); + String subPackage = matcher.group("subPackage"); + List entityPackageSplit = Arrays.asList(entityPackage.split("\\.")); + while (expression.contains(".parent")) { + if (entityPackageSplit.size() == 0) { + throw new RuntimeException("Expression [.parent] has exceeded the maximum limit."); + } + int index = expression.lastIndexOf(".parent"); + if (index != -1) { + expression = expression.substring(0, index); + entityPackageSplit = entityPackageSplit.subList(0, entityPackageSplit.size() - 1); + } + } + expression = expression.replace("entityPackage", String.join(".", entityPackageSplit)); + return expression + subPackage; + } + + public static boolean isGetterMethod(String methodName, String property) { if (methodName.startsWith("get") && methodName.length() > 3) { return firstCharToUpperCase(property).concat("()").equals(methodName.substring(3));