基于MybatisGenerator一键生成工程代码,重复性工作交给它准没错

8bd0aa4b09f4da0da562be8d50542b01.jpg
现在大多数的项目都是分多层结构,经典的如遵循MVC规范(Model-View-Controller),如果按照DDD领域模型设计可能会划分更多层,每一层需要创建多个类似模式的类文件和内容,包括类名、注释、属性、方法等,基于数据模型生成代码的插件和工具有很多,比如mybatis-plus、mybatis-generator、mybatisx等,当然市面上也有许多代码自动生成的产品,这些代码生成方式大部分都是生成固定文件结构,但是大多公司一般有自己的一套框架结构或者重新设计的分层结构,这个时候就需要自定义代码生成文件格式,包括生成文件位置和内容格式,今天为大家带来基于mybatis-generator插件的方式实现自定义代码结构,更好的适配现有代码工程。

基础配置

基于插件基本功能生成的代码,包括Do.javaExample.javaMapper.javaMapper.xml文件,其中生成内容没有对应的注释信息,或者配置生成的配置信息不够人性化,基本无用。

插件配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.4.2</version>
<dependencies>
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.4.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.32</version>
</dependency>
</dependencies>
<configuration>
<!-- 输出详细信息 -->
<verbose>true</verbose>
<!-- 覆盖生成的类文件 -->
<overwrite>true</overwrite>
<!-- 定义配置文件 -->
<configurationFile>${basedir}/src/main/resources/generator-configuration.xml</configurationFile>
</configuration>
</plugin>
</plugins>

配置Maven插件,可以比较容易的触发生成代码。
image.png

配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!-- 设置生成的文件适用于哪个Mybatis 版本 -->
<context id="default" targetRuntime="MyBatis3">
<!-- 生成RowBounds方法 -->
<plugin type="org.mybatis.generator.plugins.RowBoundsPlugin"/>
<!-- 覆盖XML Mapper文件,POM文件中配置的是Class文件覆盖 -->
<plugin type="org.mybatis.generator.plugins.UnmergeableXmlMappersPlugin"/>

<!-- 旨在创建class时,对注释进行控制 -->
<commentGenerator>
<property name="suppressDate" value="true"/>
<!-- 是否去除自动生成的注释 true:是 false:否 -->
<property name="suppressAllComments" value="true"/>
</commentGenerator>
<!-- jdbc的数据库连接 -->
<jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/code_gen?useSSL=false"
userId="root"
password="123456"/>
<!-- 非必须,类型处理器,在数据库类型和java类型之间的转换控制,默认情况下数据库中的decimal,bigint在Java对应是sql下的BigDecimal类 -->
<javaTypeResolver>
<!-- 使用常用的基本类型代替sql包下的引用类型 -->
<property name="forceBigDecimals" value="false"/>
</javaTypeResolver>
<!-- 生成的实体类所在的包 -->
<javaModelGenerator targetPackage="com.example.codegen.domain" targetProject="src/main/java">
<!-- 是否允许子包 -->
<property name="enableSubPackages" value="true"/>
<!-- 是否清理从数据库中查询出的字符串左右两边的空白字符 -->
<property name="trimStrings" value="false"/>
</javaModelGenerator>
<!-- 生成的mapper xml文件的包和位置 -->
<sqlMapGenerator targetPackage="mapper" targetProject="src/main/resources">
<!-- 针对数据库的一个配置,是否把schema作为字包名 -->
<property name="enableSubPackages" value="false"/>
</sqlMapGenerator>
<!-- 生成的mapper class文件的包和位置 -->
<javaClientGenerator type="XMLMAPPER" targetPackage="com.example.codegen.mapper" targetProject="src/main/java">
<property name="enableSubPackages" value="false"/>
</javaClientGenerator>

<!-- 表配置 -->
<table tableName="system_users" domainObjectName="SystemUsersDo"/>
</context>
</generatorConfiguration>

配置注释信息写的比较清楚,这里给出部分配置信息,能够满足大部分需求,如有特殊需求可以参考 官方文档

效果展示

**生成代码总览**具体生成内容介于文章内容就不做展示,大家可以实际配置生成。
image.png

准备工作

进入正题配置我们的自定义插件配置,基于MybatisGenerator提供的上下文信息可以方便的获取到元数据信息,自定义插件有两种解决方案:

  1. 在项目工程中定义插件,执行生成代码可以动态加载对应的插件;
  2. 基于MybatisGenerator核心包修改,不侵入项目工程,可以方便的分享给其他人使用;

当然,本篇文章主要介绍基于MybatisGenerator核心包修改的方式,简单在GitHub上边搜索mybatis-generator-core发现魔改项目还挺多,接下来实际进行操作。

拉取核心包

可以从GitHub直接拉取魔改的仓库,或者直接下载源码解压,我这里直接从仓库中找到源码并解压,mybatis-generator-core-1.4.2-sources。
image.png

导入工程

  • 将源码包移动到/src/main/java中;
  • 从/META-INF/maven/org.mybatis.generator/mybatis-generator-core中将pom.xml文件复制一份出来放到根目录下并删除部分内容;
  • 修改坐标,groupId或者artifactId都是可以的;
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.local.generator</groupId>
    <artifactId>mybatis-generator-core</artifactId>
    <version>1.0.0</version>
    <name>mybatis-generator-core</name>

    <properties>
    <maven.compiler.source>8</maven.compiler.source>
    <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
    <dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>2.0.6</version>
    <scope>provided</scope>
    <optional>true</optional>
    </dependency>
    <dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.20.0</version>
    <scope>provided</scope>
    <optional>true</optional>
    </dependency>
    <dependency>
    <groupId>commons-logging</groupId>
    <artifactId>commons-logging</artifactId>
    <version>1.2</version>
    <scope>provided</scope>
    <optional>true</optional>
    </dependency>
    <dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.4.5</version>
    <scope>test</scope>
    </dependency>
    <dependency>
    <groupId>org.apache.ant</groupId>
    <artifactId>ant</artifactId>
    <version>1.10.13</version>
    <scope>provided</scope>
    <optional>true</optional>
    </dependency>
    <dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-params</artifactId>
    <version>5.9.2</version>
    </dependency>
    <dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-engine</artifactId>
    <version>5.9.2</version>
    </dependency>
    <dependency>
    <groupId>org.assertj</groupId>
    <artifactId>assertj-core</artifactId>
    <version>3.24.2</version>
    </dependency>
    <dependency>
    <groupId>org.hsqldb</groupId>
    <artifactId>hsqldb</artifactId>
    <version>2.7.1</version>
    <scope>test</scope>
    </dependency>
    <dependency>
    <groupId>com.github.javaparser</groupId>
    <artifactId>javaparser-core</artifactId>
    <version>3.25.0</version>
    </dependency>
    <dependency>
    <groupId>org.jetbrains.kotlin</groupId>
    <artifactId>kotlin-stdlib</artifactId>
    <version>1.8.10</version>
    <scope>test</scope>
    </dependency>
    </dependencies>
    </project>
    其中依赖版本从parent获取,配置完成后移除parent,配置完成后注意执行mvn clean install操作,将包install到仓库中
    image.png

工程依赖自定义插件

image.png
依赖自定义的工程包,groupId和artifactId可以自行修改,我这里未变更,仅修改版本号为1.0.0,执行生成代码查看效果,我这里执行无任何变化,需要注意的是一定需要修改坐标,不然可能遇到执行出现null的情况,目测是插件执行过程中验证了某些信息。

自定义插件

说了一堆前置条件,终于到了文章的重点,自定义插件逻辑实现,本篇文章主要介绍定制化Mapper.java、实体注释优化、Service.java生成逻辑,可以参考生成更多内容,如Controller.java、Manager.java等等,生成逻辑都是相似的几乎可以CV CV CV,一个分层结构插件可能存在比较多的上下文,为了方便按照层拆分插件数量。

  • JavaMapperPlugin插件:主要定制化基础插件功能生成的Do.java、Mapper.java文件;
  • ServicePluginc插件:生成Model.javaConvertor.javaService.javaServiceImpl.java文件;

添加配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!-- 设置生成的文件适用于哪个Mybatis 版本 -->
<context id="default" targetRuntime="MyBatis3">
<!-- 自定义全局属性,根据实际情况进行修改 -->
<property name="author" value="reboot"/>
<property name="baseProject" value="/Users/xx/Codes/IdeaProjects/Demos/code-gen"/>

<!-- 生成RowBounds方法 -->
<plugin type="org.mybatis.generator.plugins.RowBoundsPlugin"/>
<!-- 覆盖XML Mapper文件,POM文件中配置的是Class文件覆盖 -->
<plugin type="org.mybatis.generator.plugins.UnmergeableXmlMappersPlugin"/>
<!-- 自定义插件,Mapper生成、扩展添加注释、使用通用接口 -->
<plugin type="org.mybatis.generator.plugins.custom.JavaMapperPlugin"/>
<!-- 自定义插件,Service生成 -->
<plugin type="org.mybatis.generator.plugins.custom.ServicePlugin"/>

<!-- 旨在创建class时,对注释进行控制 -->
<commentGenerator>
<property name="suppressDate" value="true"/>
<!-- 是否去除自动生成的注释 true:是 false:否 -->
<property name="suppressAllComments" value="true"/>
</commentGenerator>
<!-- jdbc的数据库连接 -->
<jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/code_gen?useSSL=false"
userId="root"
password="123456"/>
<!-- 非必须,类型处理器,在数据库类型和java类型之间的转换控制,默认情况下数据库中的decimal,bigint在Java对应是sql下的BigDecimal类 -->
<javaTypeResolver>
<!-- 使用常用的基本类型代替sql包下的引用类型 -->
<property name="forceBigDecimals" value="false"/>
</javaTypeResolver>
<!-- 生成的实体类所在的包 -->
<javaModelGenerator targetPackage="com.example.codegen.domain" targetProject="src/main/java">
<!-- 是否允许子包 -->
<property name="enableSubPackages" value="true"/>
<!-- 是否清理从数据库中查询出的字符串左右两边的空白字符 -->
<property name="trimStrings" value="false"/>
</javaModelGenerator>
<!-- 生成的mapper xml文件的包和位置 -->
<sqlMapGenerator targetPackage="mapper" targetProject="src/main/resources">
<!-- 针对数据库的一个配置,是否把schema作为字包名 -->
<property name="enableSubPackages" value="false"/>
</sqlMapGenerator>
<!-- 生成的mapper class文件的包和位置 -->
<javaClientGenerator type="XMLMAPPER" targetPackage="com.example.codegen.mapper" targetProject="src/main/java">
<property name="enableSubPackages" value="false"/>
</javaClientGenerator>

<!-- 表配置 -->
<table tableName="system_users" domainObjectName="SystemUsersDo">
<property name="comment" value="系统用户"/>
<generatedKey column="id" sqlStatement="Mysql" identity="true"/>
</table>
</context>
</generatorConfiguration>

修改点如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!-- 自定义全局属性,根据实际情况进行修改 -->
<property name="author" value="reboot"/>
<property name="baseProject" value="/Users/xx/Codes/IdeaProjects/Demos/code-gen"/>

<!-- 自定义插件,Mapper生成、扩展添加注释、使用通用接口 -->
<plugin type="org.mybatis.generator.plugins.custom.JavaMapperPlugin"/>
<!-- 自定义插件,Service生成 -->
<plugin type="org.mybatis.generator.plugins.custom.ServicePlugin"/>

<!-- 表配置,其中comment属性为自定义添加 -->
<table tableName="system_users" domainObjectName="SystemUsersDo">
<property name="comment" value="系统用户"/>
<generatedKey column="id" sqlStatement="Mysql" identity="true"/>
</table>

JavaMapperPlugin插件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package org.mybatis.generator.plugins.custom;

import org.mybatis.generator.api.GeneratedJavaFile;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.DefaultJavaFormatter;
import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
import org.mybatis.generator.api.dom.java.Interface;
import org.mybatis.generator.api.dom.java.JavaVisibility;
import org.mybatis.generator.api.dom.java.TopLevelClass;

import java.util.ArrayList;
import java.util.List;

/**
* JavaMapper插件
*
* @author reboot
*/
public class JavaMapperPlugin extends PluginAdapter {

private List<String> warnings;
private String tableComment;
private String author;
private String baseProject;

private static final String MAPPER_BASE = "/src/main/java";
private static final String MAPPER_PACKAGE = "com.example.codegen.mapper";

@Override
public boolean validate(List<String> warnings) {
this.warnings = warnings;
return true;
}

@Override
public List<GeneratedJavaFile> contextGenerateAdditionalJavaFiles(IntrospectedTable introspectedTable) {
tableComment = introspectedTable.getTableConfigurationProperty("comment");
author = introspectedTable.getContext().getProperty("author");
baseProject = introspectedTable.getContext().getProperty("baseProject");

List<GeneratedJavaFile> javaFiles = new ArrayList<>();
// DO
javaFiles.add(generateDoFile(introspectedTable));
// Mapper
javaFiles.add(generateMapperFile(introspectedTable));

return javaFiles;
}

/**
* 生成DO文件
*
* @param introspectedTable 表信息
* @return {@link GeneratedJavaFile}
*/
private GeneratedJavaFile generateDoFile(IntrospectedTable introspectedTable) {
String fullDoName = introspectedTable.getBaseRecordType();
String doName = PluginUtils.getClassName(fullDoName);

PluginUtils.fileExistCheck(fullDoName, baseProject + MAPPER_BASE, warnings);

TopLevelClass doTopLevelClass = PluginUtils.generateEntity(introspectedTable, this.context, fullDoName,
PluginUtils.classDoc(tableComment + "数据模型", doName, author));
return new GeneratedJavaFile(doTopLevelClass, baseProject + MAPPER_BASE, new DefaultJavaFormatter());
}

/**
* 生成Mapper文件
*
* @param introspectedTable 表信息
* @return {@link GeneratedJavaFile}
*/
private GeneratedJavaFile generateMapperFile(IntrospectedTable introspectedTable) {
String fullDoName = introspectedTable.getBaseRecordType();
String doName = PluginUtils.getClassName(fullDoName);
String mapperName = doName + "Mapper";
String fullMapperName = MAPPER_PACKAGE + "." + mapperName;
String exampleName = doName + "Example";
String fullExampleName = fullDoName + "Example";

PluginUtils.fileExistCheck(fullMapperName, baseProject + MAPPER_BASE, warnings);

Interface baseMapperInterface = new Interface(new FullyQualifiedJavaType(fullMapperName));
baseMapperInterface.addFileCommentLine(PluginUtils.fileComment());
baseMapperInterface.setVisibility(JavaVisibility.PUBLIC);
baseMapperInterface.addJavaDocLine(PluginUtils.classDoc(tableComment + "Mapper", mapperName, author));
baseMapperInterface.addSuperInterface(new FullyQualifiedJavaType("BaseMapper<" + doName + "," + exampleName + ">"));

baseMapperInterface.addImportedType(new FullyQualifiedJavaType("com.example.codegen.mapper.BaseMapper"));
baseMapperInterface.addImportedType(new FullyQualifiedJavaType(fullDoName));
baseMapperInterface.addImportedType(new FullyQualifiedJavaType(fullExampleName));

return new GeneratedJavaFile(baseMapperInterface, baseProject + MAPPER_BASE, new DefaultJavaFormatter());
}
}

ServicePluginc插件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
package org.mybatis.generator.plugins.custom;

import org.mybatis.generator.api.GeneratedJavaFile;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.DefaultJavaFormatter;
import org.mybatis.generator.api.dom.java.Field;
import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
import org.mybatis.generator.api.dom.java.JavaVisibility;
import org.mybatis.generator.api.dom.java.TopLevelClass;
import org.mybatis.generator.internal.util.JavaBeansUtil;

import java.util.ArrayList;
import java.util.List;

/**
* Service插件
*
* @author reboot
*/
public class ServicePlugin extends PluginAdapter {

private List<String> warnings;
private String tableComment;
private String author;
private String baseProject;

private static final String SERVICE_BASE = "/src/main/java";
private static final String SERVICE_PACKAGE = "com.example.codegen.service";
private static final String MAPPER_PACKAGE = "com.example.codegen.mapper";

@Override
public boolean validate(List<String> warnings) {
this.warnings = warnings;
return true;
}

@Override
public List<GeneratedJavaFile> contextGenerateAdditionalJavaFiles(IntrospectedTable introspectedTable) {
tableComment = introspectedTable.getTableConfigurationProperty("comment");
author = introspectedTable.getContext().getProperty("author");
baseProject = introspectedTable.getContext().getProperty("baseProject");

List<GeneratedJavaFile> javaFiles = new ArrayList<>();
// Service
javaFiles.add(generateServiceFile(introspectedTable));

return javaFiles;
}

/**
* 生成Service文件
*
* @param introspectedTable 表信息
* @return {@link GeneratedJavaFile}
*/
private GeneratedJavaFile generateServiceFile(IntrospectedTable introspectedTable) {
String fullDoName = introspectedTable.getBaseRecordType();
String doName = PluginUtils.getClassName(fullDoName);
String serviceName = doName.replace("Do", "Service");
String fullServiceName = SERVICE_PACKAGE + "." + serviceName;
String mapperName = doName + "Mapper";
String fullMapperName = MAPPER_PACKAGE + "." + mapperName;

PluginUtils.fileExistCheck(fullServiceName, baseProject + SERVICE_PACKAGE, warnings);

TopLevelClass serviceTopLevelClass = new TopLevelClass(fullServiceName);
serviceTopLevelClass.addFileCommentLine(PluginUtils.fileComment());
serviceTopLevelClass.setVisibility(JavaVisibility.PUBLIC);
serviceTopLevelClass.addJavaDocLine(PluginUtils.classDoc(tableComment + "领域服务实现", serviceName, author));
serviceTopLevelClass.addAnnotation("@Component");
Field mapperField = new Field(JavaBeansUtil.getValidPropertyName(mapperName), new FullyQualifiedJavaType(mapperName));
mapperField.setVisibility(JavaVisibility.PUBLIC);
mapperField.addAnnotation("@Autowired");
serviceTopLevelClass.addField(mapperField);

serviceTopLevelClass.addImportedType("org.springframework.stereotype.Component");
serviceTopLevelClass.addImportedType("org.springframework.beans.factory.annotation.Autowired");
serviceTopLevelClass.addImportedType(fullMapperName);

return new GeneratedJavaFile(serviceTopLevelClass, baseProject + SERVICE_BASE, new DefaultJavaFormatter());
}
}

抽取通用工具

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package org.mybatis.generator.plugins.custom;

import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.dom.java.Field;
import org.mybatis.generator.api.dom.java.JavaVisibility;
import org.mybatis.generator.api.dom.java.TopLevelClass;
import org.mybatis.generator.config.Context;
import org.mybatis.generator.internal.util.JavaBeansUtil;

import java.io.File;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

/**
* 插件工具类
*
* @author reboot
*/
public class PluginUtils {

/**
* 文件存在性检查
*
* @param fullName 全名
* @param basePath 基本路径
* @param warnings 警告
*/
public static void fileExistCheck(String fullName, String basePath, List<String> warnings) {
String path = String.join(File.separator, basePath, fullName.replace(".", File.separator), ".java");
if (new File(path).exists()) {
warnings.add("java file" + fullName + " already exists in " + basePath + " and will be overridden.");
}
}

/**
* 获取类名
*
* @param recordType 记录类型
* @return {@link String}
*/
public static String getClassName(String recordType) {
return recordType.substring(recordType.lastIndexOf(".") + 1);
}

/**
* 文件注释,自行实现
*
* @return {@link String}
*/
public static String fileComment() {
return "/* 文件头 2023 */";
}

/**
* 类注释
*
* @param remark 备注
* @param className 类名
* @param author 作者
* @return {@link String}
*/
public static String classDoc(String remark, String className, String author) {
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm");
StringBuilder javaDoc = new StringBuilder();
javaDoc.append("/**\n");
javaDoc.append(" * " + remark + "\n");
javaDoc.append(" *\n");
javaDoc.append(" * @author " + author + "\n");
javaDoc.append(" * @version " + className + ".java, v0.1 " + LocalDateTime.now().format(dateTimeFormatter) + " " + author + "\n");
javaDoc.append(" */");
return javaDoc.toString();
}

/**
* 属性注释
*
* @param remark 备注
* @return {@link String}
*/
public static String fieldDoc(String remark) {
StringBuilder fieldDoc = new StringBuilder();
fieldDoc.append("/**\n");
fieldDoc.append("\t * " + remark);
fieldDoc.append("\n");
fieldDoc.append("\t */");
return fieldDoc.toString();
}

/**
* 生成实体
*
* @param introspectedTable 表信息
* @param context 上下文
* @param fullName 全限定名
* @param javaDoc java注释
* @return {@link TopLevelClass}
*/
public static TopLevelClass generateEntity(IntrospectedTable introspectedTable, Context context, String fullName, String javaDoc) {
TopLevelClass topLevelClass = new TopLevelClass(fullName);
topLevelClass.addFileCommentLine(fileComment());
topLevelClass.setVisibility(JavaVisibility.PUBLIC);
topLevelClass.addAnnotation("@Data");
topLevelClass.addImportedType("lombok.Data");
topLevelClass.addJavaDocLine(javaDoc);
for (IntrospectedColumn introspectedColumn : introspectedTable.getAllColumns()) {
Field field = JavaBeansUtil.getJavaBeansField(introspectedColumn, context, introspectedTable);
field.addJavaDocLine(fieldDoc(introspectedColumn.getRemarks()));
topLevelClass.addField(field);
topLevelClass.addImportedType(field.getType());
}
return topLevelClass;
}
}

验证效果

image.png

SystemUsersDo.java

image.png

SystemUsersDoMapper.java

image.png

SystemUsersService.java

image.png
Service这里仅仅举个例子,我写的插件生成内容比较简单,可以根据实际情况生成。

总结

虽说不建议重复造轮子,但是轮子没有那么好,就只好基于轮子造轮子了,上边的写法可能不是最好的,但是能满足项目工程总体框架结构,一般的后台系统生成基本的CRUD功能还是非常方便的,基于这种方式几乎项目中相同模式的代码都可以生成,不要让基础的功能浪费大量时间。

评论