mirror of
https://gitee.com/mybatis-flex/mybatis-flex.git
synced 2025-12-08 01:28:24 +08:00
!90 refactor:重构 mybatis-flex-processor 模块
Merge pull request !90 from 王帅/main
This commit is contained in:
commit
0149830eed
@ -12,11 +12,6 @@
|
||||
<artifactId>mybatis-flex-processor</artifactId>
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.mybatis</groupId>
|
||||
<artifactId>mybatis</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.mybatis-flex</groupId>
|
||||
<artifactId>mybatis-flex-annotation</artifactId>
|
||||
|
||||
@ -1,70 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
|
||||
* <p>
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.mybatisflex.processor;
|
||||
|
||||
|
||||
import javax.annotation.processing.Filer;
|
||||
import javax.tools.FileObject;
|
||||
import javax.tools.StandardLocation;
|
||||
import java.io.*;
|
||||
import java.util.Properties;
|
||||
|
||||
|
||||
class MyBatisFlexProps {
|
||||
|
||||
private static final String DEFAULT_ENCODING = "UTF-8";
|
||||
protected Properties properties = new Properties();
|
||||
|
||||
public MyBatisFlexProps(Filer filer) {
|
||||
InputStream inputStream = null;
|
||||
try {
|
||||
FileObject propertiesFileObject = filer.getResource(StandardLocation.CLASS_OUTPUT, ""
|
||||
, "mybatis-flex.properties");
|
||||
|
||||
File propertiesFile = new File(propertiesFileObject.toUri());
|
||||
if (propertiesFile.exists()) {
|
||||
inputStream = propertiesFileObject.openInputStream();
|
||||
} else if (getClass().getClassLoader().getResource("mybatis-flex.properties") != null) {
|
||||
inputStream = getClass().getClassLoader().getResourceAsStream("mybatis-flex.properties");
|
||||
} else {
|
||||
File pomXmlFile = new File(propertiesFile.getParentFile().getParentFile().getParentFile(), "pom.xml");
|
||||
if (pomXmlFile.exists()) {
|
||||
propertiesFile = new File(pomXmlFile.getParentFile(), "src/main/resources/mybatis-flex.properties");
|
||||
}
|
||||
}
|
||||
|
||||
if (inputStream == null && propertiesFile.exists()) {
|
||||
inputStream = new FileInputStream(propertiesFile);
|
||||
}
|
||||
|
||||
if (inputStream != null) {
|
||||
properties.load(new InputStreamReader(inputStream, DEFAULT_ENCODING));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
} finally {
|
||||
if (inputStream != null) {
|
||||
try {
|
||||
inputStream.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Properties getProperties() {
|
||||
return properties;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,340 @@
|
||||
/*
|
||||
* Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
|
||||
* <p>
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.mybatisflex.processor;
|
||||
|
||||
import com.mybatisflex.annotation.Column;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import com.mybatisflex.processor.builder.ContentBuilder;
|
||||
import com.mybatisflex.processor.config.ConfigurationKey;
|
||||
import com.mybatisflex.processor.config.MybatisFlexConfig;
|
||||
import com.mybatisflex.processor.util.FileUtil;
|
||||
import com.mybatisflex.processor.util.StrUtil;
|
||||
|
||||
import javax.annotation.processing.AbstractProcessor;
|
||||
import javax.annotation.processing.Filer;
|
||||
import javax.annotation.processing.ProcessingEnvironment;
|
||||
import javax.annotation.processing.RoundEnvironment;
|
||||
import javax.lang.model.SourceVersion;
|
||||
import javax.lang.model.element.*;
|
||||
import javax.lang.model.type.DeclaredType;
|
||||
import javax.lang.model.type.TypeKind;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import javax.lang.model.util.Types;
|
||||
import javax.tools.JavaFileObject;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.Writer;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.nio.file.Files;
|
||||
import java.sql.Time;
|
||||
import java.sql.Timestamp;
|
||||
import java.time.*;
|
||||
import java.time.chrono.JapaneseDate;
|
||||
import java.util.*;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
/**
|
||||
* MyBatis Flex Processor.
|
||||
*
|
||||
* @author 王帅
|
||||
* @since 2023-06-22
|
||||
*/
|
||||
public class MybatisFlexProcessor extends AbstractProcessor {
|
||||
|
||||
private static final List<String> DEFAULT_SUPPORT_COLUMN_TYPES = Arrays.asList(
|
||||
int.class.getName(), Integer.class.getName(),
|
||||
short.class.getName(), Short.class.getName(),
|
||||
long.class.getName(), Long.class.getName(),
|
||||
float.class.getName(), Float.class.getName(),
|
||||
double.class.getName(), Double.class.getName(),
|
||||
boolean.class.getName(), Boolean.class.getName(),
|
||||
Date.class.getName(), java.sql.Date.class.getName(), Time.class.getName(), Timestamp.class.getName(),
|
||||
Instant.class.getName(), LocalDate.class.getName(), LocalDateTime.class.getName(), LocalTime.class.getName(),
|
||||
OffsetDateTime.class.getName(), OffsetTime.class.getName(), ZonedDateTime.class.getName(),
|
||||
Year.class.getName(), Month.class.getName(), YearMonth.class.getName(), JapaneseDate.class.getName(),
|
||||
byte[].class.getName(), Byte[].class.getName(), Byte.class.getName(),
|
||||
BigInteger.class.getName(), BigDecimal.class.getName(),
|
||||
char.class.getName(), String.class.getName(), Character.class.getName()
|
||||
);
|
||||
|
||||
private Filer filer;
|
||||
private Types typeUtils;
|
||||
private MybatisFlexConfig configuration;
|
||||
|
||||
@Override
|
||||
public synchronized void init(ProcessingEnvironment processingEnvironment) {
|
||||
super.init(processingEnvironment);
|
||||
this.filer = processingEnvironment.getFiler();
|
||||
this.typeUtils = processingEnvironment.getTypeUtils();
|
||||
this.configuration = new MybatisFlexConfig(filer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
|
||||
if (!roundEnv.processingOver()) {
|
||||
System.out.println("mybatis flex processor run start...");
|
||||
|
||||
// 不启用 APT 功能
|
||||
if ("false".equalsIgnoreCase(configuration.get(ConfigurationKey.ENABLE))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 是否所有的类常量都生成在 Tables 类里
|
||||
boolean allInTables = "true".equalsIgnoreCase(configuration.get(ConfigurationKey.ALL_IN_TABLES));
|
||||
|
||||
StringBuilder importBuilder;
|
||||
StringBuilder fieldBuilder;
|
||||
|
||||
if (allInTables) {
|
||||
importBuilder = new StringBuilder();
|
||||
fieldBuilder = new StringBuilder();
|
||||
} else {
|
||||
fieldBuilder = null;
|
||||
importBuilder = null;
|
||||
}
|
||||
|
||||
// 其他配置选项
|
||||
String genPath = configuration.get(ConfigurationKey.GEN_PATH);
|
||||
String tablesPackage = configuration.get(ConfigurationKey.TABLES_PACKAGE);
|
||||
String mappersPackage = configuration.get(ConfigurationKey.MAPPERS_PACKAGE);
|
||||
String baseMapperClass = configuration.get(ConfigurationKey.BASE_MAPPER_CLASS);
|
||||
String tablesDefSuffix = configuration.get(ConfigurationKey.TABLES_DEF_SUFFIX);
|
||||
String tablesNameStyle = configuration.get(ConfigurationKey.TABLE_NAME_STYLE);
|
||||
String tablesClassName = configuration.get(ConfigurationKey.TABLES_CLASS_NAME);
|
||||
String mappersGenerateEnable = configuration.get(ConfigurationKey.MAPPERS_GENERATE_ENABLE);
|
||||
|
||||
String[] entityIgnoreSuffixes = configuration.get(ConfigurationKey.IGNORE_SUFFIXES).split(",");
|
||||
|
||||
// 如果不指定 Tables 生成包,那么 Tables 文件就会和最后一个 entity 文件在同一个包
|
||||
String entityClassReference = null;
|
||||
|
||||
// 获取需要生成的类,开始构建文件
|
||||
Set<? extends Element> elementsAnnotatedWith = roundEnv.getElementsAnnotatedWith(Table.class);
|
||||
|
||||
int size = elementsAnnotatedWith.size();
|
||||
int index = 0;
|
||||
|
||||
for (Element entityClassElement : elementsAnnotatedWith) {
|
||||
|
||||
index++;
|
||||
|
||||
// 获取 Table 注解
|
||||
Table table = entityClassElement.getAnnotation(Table.class);
|
||||
|
||||
assert table != null;
|
||||
|
||||
// 类属性
|
||||
Map<String, String> propertyAndColumns = new LinkedHashMap<>();
|
||||
// 默认查询的属性,非 isLarge 字段
|
||||
List<String> defaultColumns = new ArrayList<>();
|
||||
|
||||
TypeElement classElement = (TypeElement) entityClassElement;
|
||||
do {
|
||||
// 获取类属性和默认查询字段
|
||||
fillPropertyAndColumns(propertyAndColumns, defaultColumns, classElement, table.camelToUnderline());
|
||||
classElement = (TypeElement) typeUtils.asElement(classElement.getSuperclass());
|
||||
} while (classElement != null);
|
||||
|
||||
// 获取 entity 类名
|
||||
String entityClass = entityClassElement.toString();
|
||||
String entityClassName = StrUtil.getClassName(entityClass);
|
||||
|
||||
// 处理 entity 后缀
|
||||
for (String entityIgnoreSuffix : entityIgnoreSuffixes) {
|
||||
if (entityClassName.endsWith(entityIgnoreSuffix.trim())) {
|
||||
entityClassName = entityClassName.substring(0, entityClassName.length() - entityIgnoreSuffix.length());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 生成 TableDef 文件
|
||||
String tableDefPackage = StrUtil.buildTableDefPackage(entityClass);
|
||||
String tableDefClassName = entityClassName.concat("TableDef");
|
||||
String tableDefContent = ContentBuilder.buildTableDef(table, entityClass, entityClassName, allInTables, tableDefPackage, tableDefClassName, tablesNameStyle, tablesDefSuffix, propertyAndColumns, defaultColumns);
|
||||
processGenClass(genPath, tableDefPackage, tableDefClassName, tableDefContent);
|
||||
|
||||
if (allInTables) {
|
||||
// 标记 entity 类,如果没有配置 Tables 生成位置,以 entity 位置为准
|
||||
entityClassReference = entityClass;
|
||||
// 构建 Tables 常量属性及其导包
|
||||
ContentBuilder.buildTablesField(importBuilder, fieldBuilder, table, entityClass, entityClassName, tablesNameStyle, tablesDefSuffix);
|
||||
}
|
||||
|
||||
// 是否生成 Mapper 文件
|
||||
if ("true".equalsIgnoreCase(mappersGenerateEnable) && table.mapperGenerateEnable()) {
|
||||
String realMapperPackage = StrUtil.isBlank(mappersPackage) ? StrUtil.buildMapperPackage(entityClass) : mappersPackage;
|
||||
String mapperClassName = entityClassName.concat("Mapper");
|
||||
String mapperClassContent = ContentBuilder.buildMapper(entityClass, entityClassName, realMapperPackage, mapperClassName, baseMapperClass);
|
||||
processGenClass(genPath, realMapperPackage, mapperClassName, mapperClassContent);
|
||||
}
|
||||
|
||||
// handle NPE, ensure TableDef already generate.
|
||||
if (index == size && allInTables) {
|
||||
// 生成 Tables 文件
|
||||
String realTablesPackage = StrUtil.isBlank(tablesPackage) ? StrUtil.buildTableDefPackage(entityClassReference) : tablesPackage;
|
||||
String realTablesClassName = StrUtil.isBlank(tablesClassName) ? "Tables" : tablesClassName;
|
||||
String tablesContent = ContentBuilder.buildTables(importBuilder, fieldBuilder, realTablesPackage, tablesClassName);
|
||||
processGenClass(genPath, realTablesPackage, realTablesClassName, tablesContent);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getSupportedAnnotationTypes() {
|
||||
Set<String> supportedAnnotationTypes = new HashSet<>();
|
||||
supportedAnnotationTypes.add(Table.class.getCanonicalName());
|
||||
return supportedAnnotationTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceVersion getSupportedSourceVersion() {
|
||||
return SourceVersion.latestSupported();
|
||||
}
|
||||
|
||||
private void fillPropertyAndColumns(Map<String, String> propertyAndColumns, List<String> defaultColumns, TypeElement classElement, boolean camelToUnderline) {
|
||||
for (Element fieldElement : classElement.getEnclosedElements()) {
|
||||
|
||||
// all fields
|
||||
if (ElementKind.FIELD == fieldElement.getKind()) {
|
||||
|
||||
Set<Modifier> modifiers = fieldElement.getModifiers();
|
||||
if (modifiers.contains(Modifier.STATIC)) {
|
||||
// ignore static fields
|
||||
continue;
|
||||
}
|
||||
|
||||
Column column = fieldElement.getAnnotation(Column.class);
|
||||
if (column != null && column.ignore()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// 获取 typeHandlerClass 的名称,通过 column.typeHandler() 获取会抛出异常:MirroredTypeException:
|
||||
// 参考 https://stackoverflow.com/questions/7687829/java-6-annotation-processing-getting-a-class-from-an-annotation
|
||||
final String[] typeHandlerClass = {""};
|
||||
List<? extends AnnotationMirror> annotationMirrors = fieldElement.getAnnotationMirrors();
|
||||
for (AnnotationMirror annotationMirror : annotationMirrors) {
|
||||
annotationMirror.getElementValues().forEach((BiConsumer<ExecutableElement, AnnotationValue>) (executableElement, annotationValue) -> {
|
||||
if ("typeHandler".contentEquals(executableElement.getSimpleName())) {
|
||||
typeHandlerClass[0] = annotationValue.toString();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
TypeMirror typeMirror = fieldElement.asType();
|
||||
Element element = typeUtils.asElement(typeMirror);
|
||||
if (element != null) {
|
||||
typeMirror = element.asType();
|
||||
}
|
||||
|
||||
String typeString = typeMirror.toString().trim();
|
||||
|
||||
TypeElement typeElement = null;
|
||||
if (typeMirror.getKind() == TypeKind.DECLARED) {
|
||||
typeElement = (TypeElement) ((DeclaredType) typeMirror).asElement();
|
||||
}
|
||||
|
||||
// 未配置 typeHandler 的情况下,只支持基本数据类型,不支持比如 list set 或者自定义的类等
|
||||
if ((column == null || "org.apache.ibatis.type.UnknownTypeHandler".equals(typeHandlerClass[0]))
|
||||
&& !DEFAULT_SUPPORT_COLUMN_TYPES.contains(typeString)
|
||||
&& (typeElement != null && ElementKind.ENUM != typeElement.getKind())
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
String columnName;
|
||||
if (column != null && !StrUtil.isBlank(column.value())) {
|
||||
columnName = column.value();
|
||||
} else {
|
||||
if (camelToUnderline) {
|
||||
columnName = StrUtil.camelToUnderline(fieldElement.toString());
|
||||
} else {
|
||||
columnName = fieldElement.toString();
|
||||
}
|
||||
}
|
||||
|
||||
propertyAndColumns.put(fieldElement.toString(), columnName);
|
||||
|
||||
if (column == null || (!column.isLarge() && !column.isLogicDelete())) {
|
||||
defaultColumns.add(columnName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processGenClass(String genBasePath, String genPackageName, String className, String genContent) {
|
||||
Writer writer = null;
|
||||
try {
|
||||
JavaFileObject sourceFile = filer.createSourceFile(genPackageName + "." + className);
|
||||
if (genBasePath == null || genBasePath.trim().length() == 0) {
|
||||
writer = sourceFile.openWriter();
|
||||
writer.write(genContent);
|
||||
writer.flush();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
String defaultGenPath = sourceFile.toUri().getPath();
|
||||
|
||||
// 真实的生成代码的目录
|
||||
String realPath;
|
||||
|
||||
if (FileUtil.isAbsolutePath(genBasePath)) {
|
||||
// 用户配置的路径为绝对路径
|
||||
realPath = genBasePath;
|
||||
} else {
|
||||
// 配置的是相对路径,那么则以项目根目录为相对路径
|
||||
String projectRootPath = FileUtil.getProjectRootPath(defaultGenPath);
|
||||
realPath = new File(projectRootPath, genBasePath).getAbsolutePath();
|
||||
}
|
||||
|
||||
// 通过在 test/java 目录下执行编译生成的
|
||||
boolean fromTestSource = FileUtil.isFromTestSource(defaultGenPath);
|
||||
if (fromTestSource) {
|
||||
realPath = new File(realPath, "src/test/java").getAbsolutePath();
|
||||
} else {
|
||||
realPath = new File(realPath, "src/main/java").getAbsolutePath();
|
||||
}
|
||||
|
||||
File genJavaFile = new File(realPath, (genPackageName + "." + className).replace(".", "/") + ".java");
|
||||
if (!genJavaFile.getParentFile().exists() && !genJavaFile.getParentFile().mkdirs()) {
|
||||
System.err.println(">>>>> ERROR: can not mkdirs by mybatis-flex processor for: " + genJavaFile.getParentFile());
|
||||
return;
|
||||
}
|
||||
|
||||
writer = new PrintWriter(Files.newOutputStream(genJavaFile.toPath()));
|
||||
writer.write(genContent);
|
||||
writer.flush();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (writer != null) {
|
||||
try {
|
||||
writer.close();
|
||||
} catch (IOException ignored) {
|
||||
// do nothing here.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,619 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
|
||||
* <p>
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.mybatisflex.processor;
|
||||
|
||||
|
||||
import com.mybatisflex.annotation.Column;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import org.apache.ibatis.type.UnknownTypeHandler;
|
||||
|
||||
import javax.annotation.processing.AbstractProcessor;
|
||||
import javax.annotation.processing.Filer;
|
||||
import javax.annotation.processing.ProcessingEnvironment;
|
||||
import javax.annotation.processing.RoundEnvironment;
|
||||
import javax.lang.model.SourceVersion;
|
||||
import javax.lang.model.element.*;
|
||||
import javax.lang.model.type.DeclaredType;
|
||||
import javax.lang.model.type.TypeKind;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import javax.lang.model.util.Elements;
|
||||
import javax.lang.model.util.Types;
|
||||
import javax.tools.Diagnostic;
|
||||
import javax.tools.JavaFileObject;
|
||||
import java.io.*;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.sql.Time;
|
||||
import java.sql.Timestamp;
|
||||
import java.time.*;
|
||||
import java.time.chrono.JapaneseDate;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class QueryEntityProcessor extends AbstractProcessor {
|
||||
|
||||
private static final List<String> defaultSupportColumnTypes = Arrays.asList(
|
||||
int.class.getName(), Integer.class.getName(),
|
||||
short.class.getName(), Short.class.getName(),
|
||||
long.class.getName(), Long.class.getName(),
|
||||
float.class.getName(), Float.class.getName(),
|
||||
double.class.getName(), Double.class.getName(),
|
||||
boolean.class.getName(), Boolean.class.getName(),
|
||||
Date.class.getName(), java.sql.Date.class.getName(), Time.class.getName(), Timestamp.class.getName(),
|
||||
Instant.class.getName(), LocalDate.class.getName(), LocalDateTime.class.getName(), LocalTime.class.getName(),
|
||||
OffsetDateTime.class.getName(), OffsetTime.class.getName(), ZonedDateTime.class.getName(),
|
||||
Year.class.getName(), Month.class.getName(), YearMonth.class.getName(), JapaneseDate.class.getName(),
|
||||
byte[].class.getName(), Byte[].class.getName(), Byte.class.getName(),
|
||||
BigInteger.class.getName(), BigDecimal.class.getName(),
|
||||
char.class.getName(), String.class.getName(), Character.class.getName()
|
||||
);
|
||||
|
||||
private static final String mapperTemplate = "package @package;\n" +
|
||||
"\n" +
|
||||
"import @baseMapperClass;\n" +
|
||||
"import @entityClass;\n" +
|
||||
"\n" +
|
||||
"public interface @entityNameMapper extends @baseMapperClzName<@entityName> {\n" +
|
||||
"}\n";
|
||||
|
||||
|
||||
private static final String classTableTemplate = "package @package;\n" +
|
||||
"\n" +
|
||||
"import com.mybatisflex.core.query.QueryColumn;\n" +
|
||||
"import com.mybatisflex.core.table.TableDef;\n" +
|
||||
"\n" +
|
||||
"// Auto generate by mybatis-flex, do not modify it.\n" +
|
||||
"public class @tablesClassName {\n" +
|
||||
"@classesInfo" +
|
||||
"}\n";
|
||||
|
||||
private static final String tableDefTemplate = "\n\n public static final @entityClassTableDef @tableField = new @entityClassTableDef(\"@schema\", \"@tableName\");\n";
|
||||
|
||||
private static final String singleEntityClassTemplate = "package @package;\n" +
|
||||
"\n" +
|
||||
"import com.mybatisflex.core.query.QueryColumn;\n" +
|
||||
"import com.mybatisflex.core.table.TableDef;\n" +
|
||||
"\n" +
|
||||
"// Auto generate by mybatis-flex, do not modify it.\n" +
|
||||
"public class @entityClassTableDef extends TableDef {\n" +
|
||||
"\n" +
|
||||
"@selfDef" +
|
||||
"@queryColumns" +
|
||||
"@defaultColumns" +
|
||||
"@allColumns" +
|
||||
"\n" +
|
||||
" public @entityClassTableDef(String schema, String tableName) {\n" +
|
||||
" super(schema, tableName);\n" +
|
||||
" }\n" +
|
||||
"}\n";
|
||||
|
||||
|
||||
private static final String allInTableEntityClassTemplate = "\n" +
|
||||
" public static class @entityClassTableDef extends TableDef {\n" +
|
||||
"\n" +
|
||||
"@queryColumns" +
|
||||
"@defaultColumns" +
|
||||
"@allColumns" +
|
||||
"\n" +
|
||||
" public @entityClassTableDef(String schema, String tableName) {\n" +
|
||||
" super(schema, tableName);\n" +
|
||||
" }\n" +
|
||||
" }\n";
|
||||
|
||||
|
||||
private static final String columnsTemplate = " public QueryColumn @property = new QueryColumn(this, \"@columnName\");\n";
|
||||
|
||||
private static final String defaultColumnsTemplate = "\n public QueryColumn[] DEFAULT_COLUMNS = new QueryColumn[]{@allColumns};\n";
|
||||
private static final String allColumnsTemplate = " public QueryColumn ALL_COLUMNS = new QueryColumn(this, \"*\");\n";
|
||||
|
||||
private Filer filer;
|
||||
private Elements elementUtils;
|
||||
private Types typeUtils;
|
||||
|
||||
@Override
|
||||
public synchronized void init(ProcessingEnvironment processingEnvironment) {
|
||||
super.init(processingEnvironment);
|
||||
this.filer = processingEnvironment.getFiler();
|
||||
this.elementUtils = processingEnvironment.getElementUtils();
|
||||
this.typeUtils = processingEnvironment.getTypeUtils();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
|
||||
|
||||
if (!roundEnv.processingOver()) {
|
||||
System.out.println("mybatis flex processor run start...");
|
||||
MyBatisFlexProps props = new MyBatisFlexProps(filer);
|
||||
|
||||
String enable = props.getProperties().getProperty("processor.enable", "");
|
||||
if ("false".equalsIgnoreCase(enable)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
String genPath = props.getProperties().getProperty("processor.genPath", "");
|
||||
String genTablesPackage = props.getProperties().getProperty("processor.tablesPackage");
|
||||
String baseMapperClass = props.getProperties().getProperty("processor.baseMapperClass", "com.mybatisflex.core.BaseMapper");
|
||||
String mappersGenerateEnable = props.getProperties().getProperty("processor.mappersGenerateEnable", "false");
|
||||
String genMappersPackage = props.getProperties().getProperty("processor.mappersPackage");
|
||||
|
||||
boolean allInTables = "true".equalsIgnoreCase(props.getProperties().getProperty("processor.allInTables", "false"));
|
||||
String className = props.getProperties().getProperty("processor.tablesClassName", "Tables");
|
||||
|
||||
//upperCase, lowerCase, upperCamelCase, lowerCamelCase
|
||||
String tablesNameStyle = props.getProperties().getProperty("processor.tablesNameStyle", "upperCase");
|
||||
|
||||
//包名对应的变量后缀
|
||||
String tablesDefSuffix = props.getProperties().getProperty("processor.tablesDefSuffix", "");
|
||||
|
||||
String[] entityIgnoreSuffixes = props.getProperties().getProperty("processor.entity.ignoreSuffixes", "").split(",");
|
||||
|
||||
|
||||
AtomicReference<String> entityClassName = new AtomicReference<>();
|
||||
|
||||
StringBuilder tablesContent = new StringBuilder();
|
||||
roundEnv.getElementsAnnotatedWith(Table.class).forEach((Consumer<Element>) entityClassElement -> {
|
||||
|
||||
Table table = entityClassElement.getAnnotation(Table.class);
|
||||
|
||||
entityClassName.set(entityClassElement.toString());
|
||||
|
||||
String schema = table != null && table.value().trim().length() != 0
|
||||
? table.schema()
|
||||
: "";
|
||||
|
||||
String tableName = table != null && table.value().trim().length() != 0
|
||||
? table.value()
|
||||
: firstCharToLowerCase(entityClassElement.getSimpleName().toString());
|
||||
|
||||
|
||||
Map<String, String> propertyAndColumns = new LinkedHashMap<>();
|
||||
List<String> defaultColumns = new ArrayList<>();
|
||||
|
||||
TypeElement classElement = (TypeElement) entityClassElement;
|
||||
do {
|
||||
fillPropertyAndColumns(propertyAndColumns, defaultColumns, classElement, (table == null || table.camelToUnderline()));
|
||||
classElement = (TypeElement) typeUtils.asElement(classElement.getSuperclass());
|
||||
} while (classElement != null);
|
||||
|
||||
|
||||
String entitySimpleName = entityClassElement.getSimpleName().toString();
|
||||
if (entityIgnoreSuffixes.length > 0) {
|
||||
for (String entityIgnoreSuffix : entityIgnoreSuffixes) {
|
||||
if (entitySimpleName.endsWith(entityIgnoreSuffix.trim())) {
|
||||
entitySimpleName = entitySimpleName.substring(0, entitySimpleName.length() - entityIgnoreSuffix.length());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (allInTables) {
|
||||
String content = buildTablesClass(entitySimpleName, schema, tableName, propertyAndColumns, defaultColumns, tablesNameStyle
|
||||
, tablesDefSuffix, null, allInTables);
|
||||
tablesContent.append(content);
|
||||
}
|
||||
//每一个 entity 生成一个独立的文件
|
||||
else {
|
||||
String realGenPackage = isEmpty(genMappersPackage) ? guessTablesPackage(entityClassName.get()) : genTablesPackage;
|
||||
String content = buildTablesClass(entitySimpleName, schema, tableName, propertyAndColumns, defaultColumns, tablesNameStyle
|
||||
, tablesDefSuffix, realGenPackage, allInTables);
|
||||
genClass(genPath, realGenPackage, entitySimpleName + "TableDef", content);
|
||||
}
|
||||
|
||||
//是否开启 mapper 生成功能
|
||||
if ("true".equalsIgnoreCase(mappersGenerateEnable) && table.mapperGenerateEnable()) {
|
||||
String realMapperPackage = isEmpty(genMappersPackage) ? guessMapperPackage(entityClassElement.toString()) : genMappersPackage;
|
||||
genMapperClass(genPath, realMapperPackage, entityClassElement.toString(), baseMapperClass, entitySimpleName);
|
||||
}
|
||||
});
|
||||
|
||||
if (allInTables && tablesContent.length() > 0) {
|
||||
String realGenPackage = isEmpty(genTablesPackage) ? guessTablesPackage(entityClassName.get()) : genTablesPackage;
|
||||
genTablesClass(genPath, realGenPackage, className, tablesContent.toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isEmpty(String str) {
|
||||
return str == null || str.trim().length() == 0;
|
||||
}
|
||||
|
||||
private String guessTablesPackage(String entityClassName) {
|
||||
StringBuilder guessPackage = new StringBuilder();
|
||||
if (!entityClassName.contains(".")) {
|
||||
guessPackage.append("table");// = "table";
|
||||
} else {
|
||||
guessPackage.append(entityClassName, 0, entityClassName.lastIndexOf(".")).append(".table");
|
||||
}
|
||||
return guessPackage.toString();
|
||||
}
|
||||
|
||||
|
||||
private void fillPropertyAndColumns(Map<String, String> propertyAndColumns, List<String> defaultColumns, TypeElement classElement, boolean camelToUnderline) {
|
||||
for (Element fieldElement : classElement.getEnclosedElements()) {
|
||||
|
||||
//all fields
|
||||
if (ElementKind.FIELD == fieldElement.getKind()) {
|
||||
|
||||
|
||||
Set<Modifier> modifiers = fieldElement.getModifiers();
|
||||
if (modifiers.contains(Modifier.STATIC)) {
|
||||
//ignore static fields
|
||||
continue;
|
||||
}
|
||||
|
||||
Column column = fieldElement.getAnnotation(Column.class);
|
||||
if (column != null && column.ignore()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
//获取 typeHandlerClass 的名称,通过 column.typeHandler() 获取会抛出异常:MirroredTypeException:
|
||||
//参考 https://stackoverflow.com/questions/7687829/java-6-annotation-processing-getting-a-class-from-an-annotation
|
||||
final String[] typeHandlerClass = {""};
|
||||
List<? extends AnnotationMirror> annotationMirrors = fieldElement.getAnnotationMirrors();
|
||||
for (AnnotationMirror annotationMirror : annotationMirrors) {
|
||||
annotationMirror.getElementValues().forEach((BiConsumer<ExecutableElement, AnnotationValue>) (executableElement, annotationValue) -> {
|
||||
if (executableElement.getSimpleName().equals("typeHandler")) {
|
||||
typeHandlerClass[0] = annotationValue.toString();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
TypeMirror typeMirror = fieldElement.asType();
|
||||
Element element = typeUtils.asElement(typeMirror);
|
||||
if (element != null) {
|
||||
typeMirror = element.asType();
|
||||
}
|
||||
|
||||
String typeString = typeMirror.toString().trim();
|
||||
|
||||
TypeElement typeElement = null;
|
||||
if (typeMirror.getKind() == TypeKind.DECLARED) {
|
||||
typeElement = (TypeElement) ((DeclaredType) typeMirror).asElement();
|
||||
}
|
||||
|
||||
//未配置 typeHandler 的情况下,只支持基本数据类型,不支持比如 list set 或者自定义的类等
|
||||
if ((column == null || typeHandlerClass[0].equals(UnknownTypeHandler.class.getName()))
|
||||
&& !defaultSupportColumnTypes.contains(typeString)
|
||||
&& (typeElement != null && ElementKind.ENUM != typeElement.getKind())
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
String columnName = column != null && column.value().trim().length() > 0 ? column.value() :
|
||||
(camelToUnderline ? camelToUnderline(fieldElement.toString()) : fieldElement.toString());
|
||||
propertyAndColumns.put(fieldElement.toString(), columnName);
|
||||
|
||||
if (column == null || (!column.isLarge() && !column.isLogicDelete())) {
|
||||
defaultColumns.add(columnName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static String guessMapperPackage(String entityClassName) {
|
||||
if (!entityClassName.contains(".")) {
|
||||
return "mapper";
|
||||
} else {
|
||||
String entityPackage = entityClassName.substring(0, entityClassName.lastIndexOf("."));
|
||||
if (entityPackage.contains(".")) {
|
||||
return entityPackage.substring(0, entityPackage.lastIndexOf(".")) + ".mapper";
|
||||
} else {
|
||||
return "mapper";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//upperCase, lowerCase, upperCamelCase, lowerCamelCase
|
||||
private static String buildName(String name, String style) {
|
||||
if ("upperCase".equalsIgnoreCase(style)) {
|
||||
return camelToUnderline(name).toUpperCase();
|
||||
} else if ("lowerCase".equalsIgnoreCase(style)) {
|
||||
return camelToUnderline(name).toLowerCase();
|
||||
} else if ("upperCamelCase".equalsIgnoreCase(style)) {
|
||||
return firstCharToUpperCase(name);
|
||||
}
|
||||
//lowerCamelCase
|
||||
else {
|
||||
return firstCharToLowerCase(name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private String buildTablesClass(String entityClass, String schema, String tableName, Map<String, String> propertyAndColumns
|
||||
, List<String> defaultColumns, String tablesNameStyle, String tablesDefSuffix, String realGenPackage, boolean allInTables) {
|
||||
|
||||
// tableDefTemplate = " public static final @entityClassTableDef @tableField = new @entityClassTableDef(\"@tableName\");\n";
|
||||
|
||||
String tableDef = tableDefTemplate.replace("@entityClass", entityClass)
|
||||
.replace("@schema", schema)
|
||||
.replace("@tableField", buildName(entityClass, tablesNameStyle)
|
||||
+ (tablesDefSuffix != null ? tablesDefSuffix.trim() : ""))
|
||||
.replace("@tableName", tableName);
|
||||
|
||||
|
||||
//columnsTemplate = " public QueryColumn @property = new QueryColumn(this, \"@columnName\");\n";
|
||||
StringBuilder queryColumns = new StringBuilder();
|
||||
propertyAndColumns.forEach((property, column) ->
|
||||
queryColumns.append(columnsTemplate.substring(allInTables ? 0 : 4) //移除 4 个空格
|
||||
.replace("@property", buildName(property, tablesNameStyle))
|
||||
.replace("@columnName", column)
|
||||
));
|
||||
|
||||
|
||||
// public QueryColumn[] ALL_COLUMNS = new QueryColumn[]{@allColumns};
|
||||
StringJoiner allColumns = new StringJoiner(", ");
|
||||
propertyAndColumns.forEach((property, column) -> allColumns.add(buildName(property, tablesNameStyle)));
|
||||
|
||||
// String allColumnsString = allColumnsTemplate.replace("@allColumns", allColumns.toString())
|
||||
// .replace("ALL_COLUMNS", buildName("allColumns", tablesNameStyle));
|
||||
|
||||
String allColumnsString = allColumnsTemplate;
|
||||
|
||||
|
||||
StringJoiner defaultColumnStringJoiner = new StringJoiner(", ");
|
||||
propertyAndColumns.forEach((property, column) -> {
|
||||
if (defaultColumns.contains(column)) {
|
||||
defaultColumnStringJoiner.add(buildName(property, tablesNameStyle));
|
||||
}
|
||||
});
|
||||
String defaultColumnsString = defaultColumnsTemplate.replace("@allColumns", defaultColumnStringJoiner.toString())
|
||||
.replace("DEFAULT_COLUMNS", buildName("defaultColumns", tablesNameStyle));
|
||||
|
||||
|
||||
// classTemplate = "\n" +
|
||||
// " public static class @entityClassTableDef extends TableDef {\n" +
|
||||
// "\n" +
|
||||
// "@queryColumns" +
|
||||
// "@allColumns" +
|
||||
// "\n" +
|
||||
// " public @entityClassTableDef(String tableName) {\n" +
|
||||
// " super(tableName);\n" +
|
||||
// " }\n" +
|
||||
// " }\n";
|
||||
|
||||
String tableClass;
|
||||
if (allInTables) {
|
||||
tableClass = allInTableEntityClassTemplate.replace("@entityClass", entityClass)
|
||||
.replace("@queryColumns", queryColumns)
|
||||
.replace("@defaultColumns", defaultColumnsString)
|
||||
.replace("@allColumns", allColumnsString);
|
||||
} else {
|
||||
tableClass = singleEntityClassTemplate
|
||||
.replace("@package", realGenPackage)
|
||||
.replace("@entityClass", entityClass)
|
||||
.replace("@selfDef", tableDef.replace("\n\n", "") + "\n")
|
||||
.replace("@queryColumns", queryColumns)
|
||||
.replace("@defaultColumns", "\n" + defaultColumnsString.substring(5)) //移除 "换行 + 4 个空格"
|
||||
.replace("@allColumns", allColumnsString.substring(4)); //移除 4 个空格
|
||||
}
|
||||
|
||||
|
||||
return allInTables ? tableDef + tableClass : tableClass;
|
||||
}
|
||||
|
||||
|
||||
private void genTablesClass(String genBasePath, String genPackageName, String className, String classContent) {
|
||||
String genContent = classTableTemplate.replace("@package", genPackageName)
|
||||
.replace("@classesInfo", classContent)
|
||||
.replace("@tablesClassName", className);
|
||||
|
||||
genClass(genBasePath, genPackageName, className, genContent);
|
||||
}
|
||||
|
||||
|
||||
private void genClass(String genBasePath, String genPackageName, String className, String genContent) {
|
||||
Writer writer = null;
|
||||
try {
|
||||
JavaFileObject sourceFile = filer.createSourceFile(genPackageName + "." + className);
|
||||
if (genBasePath == null || genBasePath.trim().length() == 0) {
|
||||
writer = sourceFile.openWriter();
|
||||
writer.write(genContent);
|
||||
writer.flush();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
String defaultGenPath = sourceFile.toUri().getPath();
|
||||
|
||||
//真实的生成代码的目录
|
||||
String realPath;
|
||||
|
||||
//用户配置的路径为绝对路径
|
||||
if (isAbsolutePath(genBasePath)) {
|
||||
realPath = genBasePath;
|
||||
}
|
||||
//配置的是相对路径,那么则以项目根目录为相对路径
|
||||
else {
|
||||
String projectRootPath = getProjectRootPath(defaultGenPath);
|
||||
realPath = new File(projectRootPath, genBasePath).getAbsolutePath();
|
||||
}
|
||||
|
||||
//通过在 test/java 目录下执行编译生成的
|
||||
boolean fromTestSource = isFromTestSource(defaultGenPath);
|
||||
if (fromTestSource) {
|
||||
realPath = new File(realPath, "src/test/java").getAbsolutePath();
|
||||
} else {
|
||||
realPath = new File(realPath, "src/main/java").getAbsolutePath();
|
||||
}
|
||||
|
||||
File genJavaFile = new File(realPath, (genPackageName + "." + className).replace(".", "/") + ".java");
|
||||
if (!genJavaFile.getParentFile().exists() && !genJavaFile.getParentFile().mkdirs()) {
|
||||
System.out.println(">>>>>ERROR: can not mkdirs by mybatis-flex processor for: " + genJavaFile.getParentFile());
|
||||
return;
|
||||
}
|
||||
|
||||
writer = new PrintWriter(new FileOutputStream(genJavaFile));
|
||||
writer.write(genContent);
|
||||
writer.flush();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (writer != null) {
|
||||
try {
|
||||
writer.close();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param genBasePath 生成路径
|
||||
* @param genPackageName 包名
|
||||
* @param entityClass 实体类名
|
||||
* @param baseMapperClass 自定义Mapper的父类全路径和类名 com.xx.mapper.BaseMapper,可通过mybatis-flex.properties 的属性processor.baseMapperClass配置, 默认为 com.mybatisflex.core.BaseMapper
|
||||
*/
|
||||
private void genMapperClass(String genBasePath, String genPackageName, String entityClass, String baseMapperClass, String entityName) {
|
||||
entityName = entityClass.substring(entityClass.lastIndexOf(".") + 1);
|
||||
String baseMapperClzName = baseMapperClass.substring(baseMapperClass.lastIndexOf(".") + 1);
|
||||
String genContent = mapperTemplate
|
||||
.replace("@package", genPackageName)
|
||||
.replace("@entityClass", entityClass)
|
||||
.replace("@entityName", entityName)
|
||||
.replace("@baseMapperClass", baseMapperClass)
|
||||
.replace("@baseMapperClzName", baseMapperClzName);
|
||||
|
||||
String mapperClassName = entityName + "Mapper";
|
||||
genClass(genBasePath, genPackageName, mapperClassName, genContent);
|
||||
}
|
||||
|
||||
|
||||
private void printMessage(String message) {
|
||||
processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING, message);
|
||||
System.out.println(message);
|
||||
}
|
||||
|
||||
public static String firstCharToLowerCase(String str) {
|
||||
char firstChar = str.charAt(0);
|
||||
if (firstChar >= 'A' && firstChar <= 'Z') {
|
||||
char[] arr = str.toCharArray();
|
||||
arr[0] += ('a' - 'A');
|
||||
return new String(arr);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
public static String firstCharToUpperCase(String string) {
|
||||
char firstChar = string.charAt(0);
|
||||
if (firstChar >= 'a' && firstChar <= 'z') {
|
||||
char[] arr = string.toCharArray();
|
||||
arr[0] -= ('a' - 'A');
|
||||
return new String(arr);
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Set<String> getSupportedAnnotationTypes() {
|
||||
Set<String> supportedAnnotationTypes = new HashSet<>();
|
||||
supportedAnnotationTypes.add(Table.class.getCanonicalName());
|
||||
return supportedAnnotationTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceVersion getSupportedSourceVersion() {
|
||||
return SourceVersion.latestSupported();
|
||||
}
|
||||
|
||||
|
||||
private boolean isFromTestSource(String path) {
|
||||
return path.contains("test-sources") || path.contains("test-annotations");
|
||||
}
|
||||
|
||||
|
||||
public static boolean isAbsolutePath(String path) {
|
||||
return path != null && (path.startsWith("/") || path.indexOf(":") > 0);
|
||||
}
|
||||
|
||||
public static String camelToUnderline(String string) {
|
||||
if (string == null || string.trim().length() == 0) {
|
||||
return "";
|
||||
}
|
||||
int len = string.length();
|
||||
StringBuilder sb = new StringBuilder(len);
|
||||
for (int i = 0; i < len; i++) {
|
||||
char c = string.charAt(i);
|
||||
if (Character.isUpperCase(c) && i > 0) {
|
||||
sb.append('_');
|
||||
}
|
||||
sb.append(Character.toLowerCase(c));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取项目的根目录,也就是根节点 pom.xml 所在的目录
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private String getProjectRootPath(String genFilePath) {
|
||||
File file = new File(genFilePath);
|
||||
int count = 20;
|
||||
return getProjectRootPath(file, count);
|
||||
}
|
||||
|
||||
|
||||
private String getProjectRootPath(File file, int count) {
|
||||
if (count <= 0) {
|
||||
return null;
|
||||
}
|
||||
if (file.isFile()) {
|
||||
return getProjectRootPath(file.getParentFile(), --count);
|
||||
} else {
|
||||
if (new File(file, "pom.xml").exists() && !new File(file.getParentFile(), "pom.xml").exists()) {
|
||||
return file.getAbsolutePath();
|
||||
} else {
|
||||
return getProjectRootPath(file.getParentFile(), --count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前 Maven 模块所在所在的目录
|
||||
*/
|
||||
private String getModuleRootPath(String genFilePath) {
|
||||
File file = new File(genFilePath);
|
||||
int count = 20;
|
||||
return getModuleRootPath(file, count);
|
||||
}
|
||||
|
||||
|
||||
private String getModuleRootPath(File file, int count) {
|
||||
if (count <= 0) {
|
||||
return null;
|
||||
}
|
||||
if (file.isFile()) {
|
||||
return getModuleRootPath(file.getParentFile(), --count);
|
||||
} else {
|
||||
if (new File(file, "pom.xml").exists()) {
|
||||
return file.getAbsolutePath();
|
||||
} else {
|
||||
return getModuleRootPath(file.getParentFile(), --count);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
|
||||
* <p>
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.mybatisflex.processor.builder;
|
||||
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import com.mybatisflex.processor.util.StrUtil;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
/**
|
||||
* 文件内容构建。
|
||||
*
|
||||
* @author 王帅
|
||||
* @since 2023-06-23
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
public class ContentBuilder {
|
||||
|
||||
private ContentBuilder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建 Mapper 文件内容。
|
||||
*/
|
||||
public static String buildMapper(String entityClass, String entityClassName,
|
||||
String mappersPackage, String mapperClassName, String baseMapperClass) {
|
||||
StringBuilder content = new StringBuilder("package ");
|
||||
content.append(mappersPackage).append(";\n\n");
|
||||
content.append("import ").append(baseMapperClass).append(";\n");
|
||||
content.append("import ").append(entityClass).append(";\n\n");
|
||||
String realEntityClassName = StrUtil.getClassName(entityClass);
|
||||
String baseMapperClassName = StrUtil.getClassName(baseMapperClass);
|
||||
content.append("public interface ").append(mapperClassName).append(" extends ").append(baseMapperClassName).append("<").append(realEntityClassName).append("> {\n}");
|
||||
return content.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建 TableDef 文件内容。
|
||||
*/
|
||||
public static String buildTableDef(Table table, String entityClass, String entityClassName, boolean allInTables,
|
||||
String tableDefPackage, String tableDefClassName,
|
||||
String tablesNameStyle, String tablesDefSuffix,
|
||||
Map<String, String> propertyAndColumns, List<String> defaultColumns) {
|
||||
StringBuilder content = new StringBuilder("package ");
|
||||
content.append(tableDefPackage).append(";\n\n");
|
||||
content.append("import com.mybatisflex.core.query.QueryColumn;\n");
|
||||
content.append("import com.mybatisflex.core.table.TableDef;\n\n");
|
||||
content.append("// Auto generate by mybatis-flex, do not modify it.\n");
|
||||
content.append("public class ").append(tableDefClassName).append(" extends TableDef {\n\n");
|
||||
if (!allInTables) {
|
||||
String schema = !StrUtil.isBlank(table.schema())
|
||||
? table.schema()
|
||||
: "";
|
||||
String tableName = !StrUtil.isBlank(table.value())
|
||||
? table.value()
|
||||
: StrUtil.firstCharToLowerCase(entityClassName);
|
||||
content.append(" public static final ").append(tableDefClassName).append(' ').append(StrUtil.buildFieldName(entityClassName.concat(tablesDefSuffix != null ? tablesDefSuffix.trim() : ""), tablesNameStyle))
|
||||
.append(" = new ").append(tableDefClassName).append("(\"").append(schema).append("\", \"").append(tableName).append("\");\n\n");
|
||||
}
|
||||
propertyAndColumns.forEach((property, column) -> content.append(" public QueryColumn ")
|
||||
.append(StrUtil.buildFieldName(property, tablesNameStyle))
|
||||
.append(" = new QueryColumn(this, \"")
|
||||
.append(column).append("\");\n"));
|
||||
content.append(" public QueryColumn ").append(StrUtil.buildFieldName("allColumns", tablesNameStyle)).append(" = new QueryColumn(this, \"*\");\n");
|
||||
StringJoiner defaultColumnJoiner = new StringJoiner(", ");
|
||||
propertyAndColumns.forEach((property, column) -> {
|
||||
if (defaultColumns.contains(column)) {
|
||||
defaultColumnJoiner.add(StrUtil.buildFieldName(property, tablesNameStyle));
|
||||
}
|
||||
});
|
||||
content.append(" public QueryColumn[] ").append(StrUtil.buildFieldName("defaultColumns", tablesNameStyle)).append(" = new QueryColumn[]{").append(defaultColumnJoiner).append("};\n\n");
|
||||
content.append(" public ").append(tableDefClassName).append("(String schema, String tableName) {\n")
|
||||
.append(" super(schema, tableName);\n")
|
||||
.append(" }\n\n}\n");
|
||||
return content.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建 Tables 文件内容。
|
||||
*/
|
||||
public static String buildTables(StringBuilder importBuilder, StringBuilder fieldBuilder,
|
||||
String tablesPackage, String tablesClassName) {
|
||||
return "package " + tablesPackage + ";\n\n" +
|
||||
importBuilder.toString() +
|
||||
"\n// Auto generate by mybatis-flex, do not modify it.\n" +
|
||||
"public class " + tablesClassName + " {\n\n" +
|
||||
" private " + tablesClassName + "() {\n" +
|
||||
" }\n\n" +
|
||||
fieldBuilder.toString() +
|
||||
"\n}\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建 Tables 文件常量属性。
|
||||
*/
|
||||
public static void buildTablesField(StringBuilder importBuilder, StringBuilder fieldBuilder, Table table,
|
||||
String entityClass, String entityClassName, String tablesNameStyle, String tablesDefSuffix) {
|
||||
String tableDefPackage = StrUtil.buildTableDefPackage(entityClass);
|
||||
String tableDefClassName = entityClassName.concat("TableDef");
|
||||
importBuilder.append("import ").append(tableDefPackage).append('.').append(tableDefClassName).append(";\n");
|
||||
String schema = !StrUtil.isBlank(table.schema())
|
||||
? table.schema()
|
||||
: "";
|
||||
String tableName = !StrUtil.isBlank(table.value())
|
||||
? table.value()
|
||||
: StrUtil.firstCharToLowerCase(entityClassName);
|
||||
fieldBuilder.append(" public static final ").append(tableDefClassName).append(' ')
|
||||
.append(StrUtil.buildFieldName(entityClassName.concat(tablesDefSuffix != null ? tablesDefSuffix.trim() : ""), tablesNameStyle))
|
||||
.append(" = new ").append(tableDefClassName).append("(\"").append(schema).append("\", \"").append(tableName).append("\");\n");
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
|
||||
* <p>
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* 内容构建。
|
||||
*/
|
||||
package com.mybatisflex.processor.builder;
|
||||
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
|
||||
* <p>
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.mybatisflex.processor.config;
|
||||
|
||||
/**
|
||||
* 配置键值。
|
||||
*
|
||||
* @author 王帅
|
||||
* @since 2023-06-22
|
||||
*/
|
||||
public enum ConfigurationKey {
|
||||
|
||||
/**
|
||||
* 全局启用 APT 开关。
|
||||
*/
|
||||
ENABLE("processor.enable", ""),
|
||||
|
||||
/**
|
||||
* APT 代码生成路径。
|
||||
*/
|
||||
GEN_PATH("processor.genPath", ""),
|
||||
|
||||
/**
|
||||
* 自定义 Tables 生成的包名。
|
||||
*/
|
||||
TABLES_PACKAGE("processor.tablesPackage", null),
|
||||
|
||||
/**
|
||||
* 自定义 Mapper 的父类。
|
||||
*/
|
||||
BASE_MAPPER_CLASS("processor.baseMapperClass", "com.mybatisflex.core.BaseMapper"),
|
||||
|
||||
/**
|
||||
* 开启 Mapper 自动生成。
|
||||
*/
|
||||
MAPPERS_GENERATE_ENABLE("processor.mappersGenerateEnable", "false"),
|
||||
|
||||
/**
|
||||
* 自定义 Mapper 生成的包名。
|
||||
*/
|
||||
MAPPERS_PACKAGE("processor.mappersPackage", null),
|
||||
|
||||
/**
|
||||
* 是否所有的类都生成在 Tables 类里。
|
||||
*/
|
||||
ALL_IN_TABLES("processor.allInTables", "false"),
|
||||
|
||||
/**
|
||||
* Tables 类名。
|
||||
*/
|
||||
TABLES_CLASS_NAME("processor.tablesClassName", "Tables"),
|
||||
|
||||
/**
|
||||
* 生成辅助类的字段风格。
|
||||
*/
|
||||
TABLE_NAME_STYLE("processor.tablesNameStyle", "upperCase"),
|
||||
|
||||
/**
|
||||
* 生成的表对应的变量后缀。
|
||||
*/
|
||||
TABLES_DEF_SUFFIX("processor.tablesDefSuffix", ""),
|
||||
|
||||
/**
|
||||
* 过滤 Entity 后缀。
|
||||
*/
|
||||
IGNORE_SUFFIXES("processor.entity.ignoreSuffixes", "");
|
||||
|
||||
private final String configKey;
|
||||
private final String defaultValue;
|
||||
|
||||
ConfigurationKey(String configKey, String defaultValue) {
|
||||
this.configKey = configKey;
|
||||
this.defaultValue = defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取配置键。
|
||||
*
|
||||
* @return 键
|
||||
*/
|
||||
public String getConfigKey() {
|
||||
return configKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取配置默认值。
|
||||
*
|
||||
* @return 默认值
|
||||
*/
|
||||
public String getDefaultValue() {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
|
||||
* <p>
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.mybatisflex.processor.config;
|
||||
|
||||
import javax.annotation.processing.Filer;
|
||||
import javax.tools.FileObject;
|
||||
import javax.tools.StandardLocation;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Mybatis Flex 生成配置。
|
||||
*
|
||||
* @author 王帅
|
||||
* @since 2023-06-22
|
||||
*/
|
||||
public class MybatisFlexConfig {
|
||||
|
||||
/**
|
||||
* 配置文件名。
|
||||
*/
|
||||
private static final String MYBATIS_FLEX = "mybatis-flex.properties";
|
||||
|
||||
/**
|
||||
* mybatis-flex.properties
|
||||
*/
|
||||
protected final Properties properties = new Properties();
|
||||
|
||||
public MybatisFlexConfig(Filer filer) {
|
||||
InputStream inputStream = null;
|
||||
try {
|
||||
FileObject propertiesFileObject = filer.getResource(StandardLocation.CLASS_OUTPUT, "", MYBATIS_FLEX);
|
||||
|
||||
File propertiesFile = new File(propertiesFileObject.toUri());
|
||||
|
||||
if (propertiesFile.exists()) {
|
||||
inputStream = propertiesFileObject.openInputStream();
|
||||
} else if (getClass().getClassLoader().getResource(MYBATIS_FLEX) != null) {
|
||||
inputStream = getClass().getClassLoader().getResourceAsStream(MYBATIS_FLEX);
|
||||
} else {
|
||||
File pomXmlFile = new File(propertiesFile.getParentFile().getParentFile().getParentFile(), "pom.xml");
|
||||
if (pomXmlFile.exists()) {
|
||||
propertiesFile = new File(pomXmlFile.getParentFile(), "src/main/resources/mybatis-flex.properties");
|
||||
}
|
||||
}
|
||||
|
||||
if (inputStream == null && propertiesFile.exists()) {
|
||||
inputStream = Files.newInputStream(propertiesFile.toPath());
|
||||
}
|
||||
|
||||
if (inputStream != null) {
|
||||
try (InputStreamReader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8)) {
|
||||
properties.load(reader);
|
||||
}
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
// do nothing here.
|
||||
} finally {
|
||||
if (inputStream != null) {
|
||||
try {
|
||||
inputStream.close();
|
||||
} catch (IOException ignored) {
|
||||
// do nothing here.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String get(ConfigurationKey key) {
|
||||
return properties.getProperty(key.getConfigKey(), key.getDefaultValue());
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
|
||||
* <p>
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* 配置选项。
|
||||
*/
|
||||
package com.mybatisflex.processor.config;
|
||||
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
|
||||
* <p>
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.mybatisflex.processor.util;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* 文件工具类。
|
||||
*
|
||||
* @author 王帅
|
||||
* @since 2023-06-22
|
||||
*/
|
||||
public class FileUtil {
|
||||
|
||||
private FileUtil() {
|
||||
}
|
||||
|
||||
public static boolean isFromTestSource(String path) {
|
||||
return path.contains("test-sources") || path.contains("test-annotations");
|
||||
}
|
||||
|
||||
public static boolean isAbsolutePath(String path) {
|
||||
return path != null && (path.startsWith("/") || path.contains(":"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取项目的根目录,也就是根节点 pom.xml 所在的目录
|
||||
*/
|
||||
public static String getProjectRootPath(String genFilePath) {
|
||||
File file = new File(genFilePath);
|
||||
int count = 20;
|
||||
return getProjectRootPath(file, count);
|
||||
}
|
||||
|
||||
public static String getProjectRootPath(File file, int count) {
|
||||
if (count <= 0) {
|
||||
return null;
|
||||
}
|
||||
if (file.isFile()) {
|
||||
return getProjectRootPath(file.getParentFile(), --count);
|
||||
} else {
|
||||
if (new File(file, "pom.xml").exists() && !new File(file.getParentFile(), "pom.xml").exists()) {
|
||||
return file.getAbsolutePath();
|
||||
} else {
|
||||
return getProjectRootPath(file.getParentFile(), --count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
|
||||
* <p>
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.mybatisflex.processor.util;
|
||||
|
||||
/**
|
||||
* 字符串工具类。
|
||||
*
|
||||
* @author 王帅
|
||||
* @since 2023-06-22
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
public class StrUtil {
|
||||
|
||||
private StrUtil() {
|
||||
}
|
||||
|
||||
/**
|
||||
* com.mybatisflex.test.entity.Account -> Account
|
||||
*/
|
||||
public static String getClassName(String str) {
|
||||
return str.substring(str.lastIndexOf(".") + 1);
|
||||
}
|
||||
|
||||
public static boolean isBlank(String str) {
|
||||
return str == null || str.trim().length() == 0;
|
||||
}
|
||||
|
||||
public static String camelToUnderline(String str) {
|
||||
if (isBlank(str)) {
|
||||
return "";
|
||||
}
|
||||
int len = str.length();
|
||||
StringBuilder sb = new StringBuilder(len);
|
||||
for (int i = 0; i < len; i++) {
|
||||
char c = str.charAt(i);
|
||||
if (Character.isUpperCase(c) && i > 0) {
|
||||
sb.append('_');
|
||||
}
|
||||
sb.append(Character.toLowerCase(c));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static String firstCharToLowerCase(String str) {
|
||||
char firstChar = str.charAt(0);
|
||||
if (firstChar >= 'A' && firstChar <= 'Z') {
|
||||
char[] arr = str.toCharArray();
|
||||
arr[0] += ('a' - 'A');
|
||||
return new String(arr);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
public static String firstCharToUpperCase(String str) {
|
||||
char firstChar = str.charAt(0);
|
||||
if (firstChar >= 'a' && firstChar <= 'z') {
|
||||
char[] arr = str.toCharArray();
|
||||
arr[0] -= ('a' - 'A');
|
||||
return new String(arr);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
public static String buildFieldName(String name, String style) {
|
||||
if ("upperCase".equalsIgnoreCase(style)) {
|
||||
return camelToUnderline(name).toUpperCase();
|
||||
} else if ("lowerCase".equalsIgnoreCase(style)) {
|
||||
return camelToUnderline(name).toLowerCase();
|
||||
} else if ("upperCamelCase".equalsIgnoreCase(style)) {
|
||||
return firstCharToUpperCase(name);
|
||||
} else {
|
||||
//lowerCamelCase
|
||||
return firstCharToLowerCase(name);
|
||||
}
|
||||
}
|
||||
|
||||
public static String buildTableDefPackage(String entityClass) {
|
||||
StringBuilder guessPackage = new StringBuilder();
|
||||
if (!entityClass.contains(".")) {
|
||||
guessPackage.append("table");
|
||||
} else {
|
||||
guessPackage.append(entityClass, 0, entityClass.lastIndexOf(".")).append(".table");
|
||||
}
|
||||
return guessPackage.toString();
|
||||
}
|
||||
|
||||
public static String buildMapperPackage(String entityClass) {
|
||||
if (!entityClass.contains(".")) {
|
||||
return "mapper";
|
||||
} else {
|
||||
String entityPackage = entityClass.substring(0, entityClass.lastIndexOf("."));
|
||||
if (entityPackage.contains(".")) {
|
||||
return entityPackage.substring(0, entityPackage.lastIndexOf(".")) + ".mapper";
|
||||
} else {
|
||||
return "mapper";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
|
||||
* <p>
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* 工具类。
|
||||
*/
|
||||
package com.mybatisflex.processor.util;
|
||||
@ -1 +1 @@
|
||||
com.mybatisflex.processor.QueryEntityProcessor
|
||||
com.mybatisflex.processor.MybatisFlexProcessor
|
||||
@ -23,5 +23,5 @@ import com.mybatisflex.annotation.Table;
|
||||
* @since 2023-06-16
|
||||
*/
|
||||
@Table("test")
|
||||
public class Test {
|
||||
public class TestEntity {
|
||||
}
|
||||
@ -1,3 +1,5 @@
|
||||
processor.mappersGenerateEnable = true
|
||||
processor.mappersGenerateEnable=true
|
||||
processor.entity.ignoreSuffixes=Entity
|
||||
#processor.allInTables=true
|
||||
#processor.baseMapperClass=com.test.mapper.ExBaseMapper
|
||||
|
||||
|
||||
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
|
||||
* <p>
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.mybatisflex.test.mapper;
|
||||
|
||||
import com.mybatisflex.core.BaseMapper;
|
||||
import com.mybatisflex.test.model.Account;
|
||||
|
||||
/**
|
||||
* @author 王帅
|
||||
* @since 2023-06-23
|
||||
*/
|
||||
public interface AccountMapper extends BaseMapper<Account> {
|
||||
}
|
||||
@ -1,3 +1,4 @@
|
||||
processor.mappersGenerateEnable = true
|
||||
processor.tablesNameStyle = lowerCase
|
||||
processor.tablesDefSuffix = Def
|
||||
processor.mappersGenerateEnable=false
|
||||
processor.tablesNameStyle=lowerCase
|
||||
processor.tablesDefSuffix=Def
|
||||
processor.allInTables=true
|
||||
|
||||
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
|
||||
* <p>
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.mybatisflex.test;
|
||||
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
@ -14,7 +30,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static com.mybatisflex.test.model.table.AccountTableDef.accountDef;
|
||||
import static com.mybatisflex.test.model.table.Tables.account_def;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(classes = AppConfig.class)
|
||||
@ -33,7 +49,7 @@ public class AccountTest implements WithAssertions {
|
||||
@Test
|
||||
public void testSelectByQuery() {
|
||||
QueryWrapper queryWrapper = QueryWrapper.create()
|
||||
.where(accountDef.age.eq(18));
|
||||
.where(account_def.age.eq(18));
|
||||
List<Account> accounts = accountMapper.selectListByQuery(queryWrapper);
|
||||
assertThat(accounts.size()).isEqualTo(1);
|
||||
assertThat(accounts.get(0).getAge()).isEqualTo(18);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user