作者:王建乐

1 前言

在日常开发工作中,我们经常用 Mybatis Generator 根据表结构生成对应的实体类和 Mapper 文件。但是 Mybatis Generator 默认生成的代码中,注释并不是我们想要的,所以一般在 Generator 配置文件中,会设置不自动生成注释。带来的问题就是自动生成代码之后,我们还要自己去类文件中把注释加上,如果生成的类较少还好,如果有生成很多类文件,自己加注释是一件繁琐的工作。

通过重写 Mybatis Generator 的 CommentGenerator 接口,可以方便地生成自己想要的注释,减少重复工作。

2 使用 Java 方式执行 Mybatis Generator

2.1 IDEA 中新建 Maven 项目

pom.xml 中引入 jar 包

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>MyGenerator</artifactId>
    <version>1.0-SNAPSHOT</version>

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

    <dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.16</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-core</artifactId>
            <version>1.3.7</version>
        </dependency>
    </dependencies>
</project>

2.2 创建 generatorConfig.xml

随便找个目录放,我放在 src/main/resources 目录下

<?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>
    <context id="mysql" defaultModelType="hierarchical" targetRuntime="MyBatis3Simple" >
        <!-- 生成的 Java 文件的编码 -->
        <property name="javaFileEncoding" value="UTF-8"/>
        <!-- 格式化 Java 代码 -->
        <property name="javaFormatter" value="org.mybatis.generator.api.dom.DefaultJavaFormatter"/>
        <!-- 格式化 XML 代码 -->
        <property name="xmlFormatter" value="org.mybatis.generator.api.dom.DefaultXmlFormatter"/>
        <commentGenerator>
            <property name="suppressAllComments" value="false" />
        </commentGenerator>
        <!-- 配置数据库连接 -->
        <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
                        connectionURL="URL"
                        userId="user" password="password">
            <!-- 设置 useInformationSchema 属性为 true -->
            <property name="useInformationSchema" value="true" />
        </jdbcConnection>
        <!-- 生成实体的位置 -->
        <javaModelGenerator targetPackage="com.jd.bulk"
                            targetProject="src/main/java">
            <property name="enableSubPackages" value="true"/>
        </javaModelGenerator>
        <!-- 生成 Mapper XML 的位置 -->
        <sqlMapGenerator targetPackage="com.jd.bulk"
                         targetProject="src/main/resources">
            <property name="enableSubPackages" value="true"/>
        </sqlMapGenerator>
        <!-- 生成 Mapper 接口的位置 -->
        <javaClientGenerator type="XMLMAPPER"
                             targetPackage="com.jd.bulk"
                             targetProject="src/main/java">
            <property name="enableSubPackages" value="true"/>
        </javaClientGenerator>
        <!-- 设置数据库的表名和实体类名 -->
        <table tableName="worker" domainObjectName="Worker"/>
    </context>
</generatorConfiguration>

2.3 创建 main 方法,运行 Generator

public class Generator {

    public static void main(String[] args) throws Exception {
        List<String> warnings = new ArrayList<>(2);
        ConfigurationParser cp = new ConfigurationParser(warnings);

        File configFile = new File("src/main/resources/generatorConfig.xml");
        Configuration config = cp.parseConfiguration(configFile);

        DefaultShellCallback callback = new DefaultShellCallback(true);

        MyBatisGenerator = new MyBatisGenerator(config, callback, warnings);
        myBatisGenerator.generate(null);
    }
}

运行 main 方法,生成默认注释如下,并不是我们想要的注释,所以一般会配置为注释不生成:

2.4 实现 CommentGenerator 接口

重写以下方法,自定义注释

public class MySQLCommentGenerator implements CommentGenerator {
    private final Properties properties;
    public MySQLCommentGenerator() {
        properties = new Properties();
    }
    @Override
    public void addConfigurationProperties(Properties properties) {
        // 获取自定义的 properties
        this.properties.putAll(properties);
    }
    /**
     * 重写给实体类加的注释
     */
    @Override
    public void addModelClassComment(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
        String author = properties.getProperty("author");
        String dateFormat = properties.getProperty("dateFormat", "yyyy-MM-dd");
        SimpleDateFormat dateFormatter = new SimpleDateFormat(dateFormat);
        // 获取表注释
        String remarks = introspectedTable.getRemarks();
        topLevelClass.addJavaDocLine("/**");
        topLevelClass.addJavaDocLine(" * " + remarks);
        topLevelClass.addJavaDocLine(" *");
        topLevelClass.addJavaDocLine(" * @author " + author);
        topLevelClass.addJavaDocLine(" * @date   " + dateFormatter.format(new Date()));
        topLevelClass.addJavaDocLine(" */");
    }
    /**
     * 重写给实体类字段加的注释
     */
    @Override
    public void addFieldComment(Field field, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) {
        // 获取列注释
        String remarks = introspectedColumn.getRemarks();
        field.addJavaDocLine("/**");
        field.addJavaDocLine(" * " + remarks);
        field.addJavaDocLine(" */");
    }
    /**
     * 重写给实体类get方法加的注释
     */
    @Override
    public void addGetterComment(Method method, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) {
        // 获取表注释
        String remarks = introspectedColumn.getRemarks();
        method.addJavaDocLine("/**");
        method.addJavaDocLine(" * " + method.getName());
        method.addJavaDocLine(" */");
    }

2.5 修改 generatorConfig.xml 配置

将 generatorConfig.xml 文件中的 commentGenerator 做如下修改,type 属性选择自己的实现类

<commentGenerator type="com.generator.MySQLCommentGenerator">
    <property name="author" value="Your Name"/>
    <property name="dateFormat" value="yyyy/MM/dd"/>
</commentGenerator>

运行 main 方法,生成注释如下:

3 使用 Maven 方式执行 Mybatis Generator

Pom.xml 文件中增加以下配置,需要引入 generator 插件时,依赖实现 CommentGenerator 接口的 jar 包,要先把自己的 jar 包 install 到本地仓库。

否则会报 com.generator.MySQLCommentGenerator 找不到,其他配置同上。

<build>
    <defaultGoal>compile</defaultGoal>
    <plugins>
        <plugin>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-maven-plugin</artifactId>
            <version>1.4.0</version>
            <configuration>
                <configurationFile>src/main/resources/generatorConfig.xml</configurationFile>
                <verbose>true</verbose>
                <overwrite>true</overwrite>
            </configuration>
            <dependencies>
                <!-- 其他的数据库,需要修改依赖 -->
                <dependency>
                    <groupId>mysql</groupId>
                    <artifactId>mysql-connector-java</artifactId>
                    <version>8.0.16</version>
                </dependency>
                <!-- 引用实现CommentGenerator接口的jar包 -->
                <dependency>
                    <groupId>org.example</groupId>
                    <artifactId>MyGenerator</artifactId>
                    <version>1.0-SNAPSHOT</version>
                </dependency>
            </dependencies>
        </plugin>
    </plugins>

4 源码分析

查看执行 Mybatis Generator 的 main 方法,主要分为两部分,解析指定的配置文件与调用生成 java 文件和 Mapper 文件的方法

4.1 解析指定的 xml 配置文件

跟踪解析 xml 文件的方法 cp.parseConfiguration(configFile) 发现,底层以 Document 形式读取 xml 文件,根据标签名解析各标签属性,保存到 Configuration 实例中。

其中解析 commentGenerator 标签的方法 parseCommentGenerator(context, childNode) 中,会获取 commentGenerator 标签的 type 属性值,也就是自定义的” com.generator.MySQLCommentGenerator” 类,放到 Context 实例中。

4.2 调用生成 java 文件和 Mapper 文件的方法

xml 配置文件解析完成,得到 Configuration 实例,后面生成文件的工作都会从 Configuration 实例中获取所需数据。生成文件的方法主要步骤为:1.连接数据库,查询表信息与列信息,2.生成文件内容,3.写入生成文件。

其中生成文件内容时,会根据 Context 的 type 属性反射创建 MySQLCommentGenerator 实例,然后调用自定义的生成注释方法。

如:生成实体类文件的注释,调用 addModelClassComment 方法

生成字段注释,调用 addFieldComment 方法

生成 Get 方法注释,调用 addGetterComment 方法

在调用 addModelClassComment,addFieldComment,addGetterComment 等生成注释的方法时,执行的都是 MySQLCommentGenerator 类的方法,这样就实现了生成自定义注释的功能。

5 总结

通过使用自定义实现 CommentGenerator 接口,让自动生成的代码加上我们想要的注释,可以省去自己加注释的麻烦。

与一般使用 Mybatis Generator 生成代码的方式一样,多实现个接口即可。

使用 Maven 方式运行时,需要在 pom.xml 引入插件时,依赖自己 jar 包。


↙↙↙阅读原文可查看相关链接,并与作者交流