MyBatis代码生成工具,你还不会吗

1,227 阅读5分钟

十、代码生成工具

  虽然MyBatis是一个简单易学的框架,但是配置XML文件也是一件相当繁琐的一个过程,而且会出现很多不容易定位的错误。当在工作中需要生成大量对象的时候,有太多的重复劳动,简直是生无可恋。所以,官方开发了 MyBatis Generator。它只需要很少量的简单配置,就可以完成大量的表到Java对象的生成工作,拥有零出错和速度快的优点,让开发人员解放出来更专注于业务逻辑的开发。
MyBatis-Generator 是MyBatis提供的一个代码生成工具,简称MBG,可以帮助我们生成数据库表对应的持久化对象(也称作 Model、PO)、操作数据库的接口(dao)、简单 SQL 的 mapper(XML 形式或注解形式)。
其官方网址为:mybatis.org/generator/

10.1 引入

  既然需要使用 MyBatis-Generator,那么在项目中就一定使用了 MyBatis 和某一种数据库,并且这些依赖应该已经在 Maven 中配置好了。例如 pom 文件中的配置:

一种是:

<!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter -->
<dependency>
    <groupid>org.mybatis.spring.boot</groupid>
    <artifactid>mybatis-spring-boot-starter</artifactid>
    <version>xx.xx.xx</version>
</dependency>

<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
    <groupid>mysql</groupid>
    <artifactid>mysql-connector-java</artifactid>
    <version>xx.xx.xx</version>
</dependency>

<!-- mybatis 代码自动生成器 -->
<!-- https://mvnrepository.com/artifact/org.mybatis.generator/mybatis-generator-core -->
<dependency>
    <groupid>org.mybatis.generator</groupid>
    <artifactid>mybatis-generator-core</artifactid>
    <version>xx.xx.xx</version>
</dependency>

另外一种方式是:

<!--插件-->
<plugins>
    <!-- https://mvnrepository.com/artifact/org.mybatis.generator/mybatis-generator-maven-plugin -->
    <plugin>
        <groupid>org.mybatis.generator</groupid>
        <artifactid>mybatis-generator-maven-plugin</artifactid>
        <version>xx.xx.xx</version>
        <!--插件设置-->
        <configuration>
            <!-- 在控制台打印执行日志 -->
            <verbose>true</verbose>
            <!-- 重复生成时会覆盖之前的文件-->
            <overwrite>true</overwrite>
            <!--自动生成配置 如果名字是generatorConfig.xml可以省略配置-->
            <!--<configurationFile>src/main/resources/generatorConfig.xml</configurationFile>-->
        </configuration>
    </plugin>
</plugins>

10.2 配置文件

  MyBatis-Generator需要一个xml配置文件,来详细配置生成代码的各种细节。例如,在项目的resources目录下新建一个mybatis-generator-config.xml配置文件。

<generatorconfiguration>
    <!-- 0个或1个 -->
    <properties />
    <!-- 0个或1个 -->
    <classpathentry />
    <!-- 1个或多个 -->
    <context>
        <!-- jdbc连接 -->
        <jdbcconnection> ... </jdbcconnection>
        <!-- schema为数据库名,tableName为对应的数据库表名 -->
        <table> ... </table>
        <!-- 注释 -->
        <commentgenerator> ... </commentgenerator>
        <!-- 类型转换 -->
        <javatyperesolver> ... </javatyperesolver>
        <!-- 生成实体类配置 -->
        <javamodelgenerator> ... </javamodelgenerator>
        <!-- 生成Mapper.xml文件配置 -->
        <sqlmapgenerator> ... </sqlmapgenerator>
        <!-- 生成Mapper.java 接口-->
        <javaclientgenerator> ... </javaclientgenerator>
    </context>
</generatorconfiguration>

10.2.1 properties

  properties 用于加载配置项或者配置文件,在整个配置文件中就可以使用 ${propertyKey} 的方式来引用配置项,对于后面需要配置的 jdbctargetProject属性会很有用。该元素有两个属性,均用来指定外部配置文件的地址,这两个属性只能使用其中一个来指定,同时出现会报错。

属性说明
resource指定classpath下的属性文件。
使用类似com/myproject/generatorConfig.properties这样的属性值
url指定文件系统上的特定位置。
例如 file:///C:/myfolder/generatorConfig.properties

10.2.2 classPathEntry

使用 classPathEntry 元素,可以在加载需要的额外的依赖包,其中,location 属性指明需要加载的 jar/zip 包的全路径。

<!-- 指定数据库驱动的jdbc驱动jar包的位置 -->
<classpathentry location="./mysql-connector-java-5.1.40.jar" />

10.2.3 context 元素

  在 generationConfiguration 的子元素中,context 是核心元素,用于配置生成一组对象的环境。元素 context 有 4 个属性可供配置:

属性说明
id必填,上下文 id,用于在生成错误时提示;
保证多个 context 的 id 不重复就行。
defaultModelType用于指定生成对象的样式
targetRuntime用于指定生成的代码的运行时环境,这个配置会影响生成的 dao 和 mapper.xml 的内容
MyBatis3:默认的值,生成基于MyBatis3.x以上版本的内容,包括XXXBySample;
MyBatis3Simple:类似MyBatis3,只是不生成XXXBySample;
还有其它可配置的值,详情见 官网
introspectedColumnImpl类全限定名,用于扩展MBG

元素 context 中,有多个子元素需要配置。同样的,context的子元素必须按照下面给出的次数和顺序进行配置:

10.2.3.1 property

用于为代码生成指定属性,或为其它元素指定属性。可以配置零个或多个,常见的property配置如下:

<!-- 
自动识别数据库关键字,默认为false。一般保留默认值,遇到数据库关键字时,按照table元素中columnOverride属性的配置进行覆盖;
    如果设置为 true, 则需按照 SqlReservedWords 中定义的关键字列表,对关键字进行定界(分隔);
    定界符(分隔符)参见 beginningDelimiter 和 endingDelimiter 的设置-->
<property name="autoDelimitKeywords" value="true" />

<!-- 生成的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" />

<!-- 指明数据库的用于标记数据库对象名的符号,比如ORACLE就是双引号,MYSQL默认是`反引号; -->
<property name="beginningDelimiter" value="`" />
<property name="endingDelimiter" value="`" /> 

注:SqlReservedWords 关键字列表

10.2.3.2 plugin

配置插件,可以有零个或多个,常见的 plugin 配置有:

<!-- 使生成的 Model 实现 Serializable 接口  -->
<plugin type="org.mybatis.generator.plugins.SerializablePlugin" />

<!--  为生成的 Model 覆写 toString() 方法 -->
<plugin type="org.mybatis.generator.plugins.ToStringPlugin" />

<!--  为生成的 Model 覆写 equals() 和 hashCode() 方法 -->
<plugin type="org.mybatis.generator.plugins.EqualsHashCodePlugin" />

<!-- 生成mysql带有分页的sql的插件  这个可以自己写,-->
<plugin type="generator.MysqlPaginationPlugin" />

10.2.3.3 commentGenerator

  可以配置0个或1个,用来配置生成的注释,默认是生成注释的,并且会在注释中添加时间等信息。但生成的注释信息没有任何价值,因而一般情况下都会屏蔽注释信息。其中type属性,以用来指定自己的注释实现类,继承DefaultCommentGenerator重写一些方法。

<commentgenerator>
	<!-- 生成的注释中是否不包含时间信息,默认为false --> 
	<property name="suppressDate" value="false" />
	<!-- 生成的注释中,时间的显示格式 -->
	 <property name="dateFormat" value="yyyy-MM-dd" />
	<!-- 是否去除自动生成的注释 -->
	<property name="suppressAllComments" value="true" />
	<!-- 是否添加数据库内的注释  -->
    <property name="addRemarkComments" value="true" />
</commentgenerator>

10.2.3.4 jdbcConnection

 用于指定数据库连接信息,该元素必选,并且只能有一个,具体如下:

<!--
	driverClass:访问数据库的JDBC驱动程序的完全限定类名
	connectionURL:访问数据库的JDBC连接URL
	userId:访问数据库的用户ID
	password:访问数据库的密码
-->
<jdbcconnection driverclass="${spring.datasource.driverClassName}" connectionurl="${spring.datasource.url}" userid="${spring.datasource.username}" password="${spring.datasource.password}">
	
	<!-- 针对oracle数据库 -->
	<property name="remarksReporting" value="true"></property>
	<!-- 针对mysql数据库 -->
    <property name="useInformationSchema" value="true"></property>
</jdbcconnection>

其中,${propertyKey} 里面是引用的外部配置文件中的propertyValue,当然也可以写死,那么就不用在, 中引入此文件了。

10.2.3.5 javaTypeResolver

可以配置 01 个,用来配置JDBC到Java中的类型转换规则,如果不进行配置,则使用默认的转换规则:

  1. 如果精度>0或者长度>18,就会使用 java.math.BigDecimal
  2. 如果精度=0并且10<=长度<=18,就会使用 java.lang.Long
  3. 如果精度=0并且5<=长度<=9,就会使用 java.lang.Integer
  4. 如果精度=0并且长度<5,就会使用 java.lang.Short

10.2.3.6 javaModelGenerator

  Java模型生成器,有且仅能配置一个,负责key类(context元素的defaultModelType属性)、JavaBean实体类、查询类的生成。

<!--生成entity类存放位置-->
<javamodelgenerator targetpackage="" targetproject="">
    
</javamodelgenerator>

javaModelGenerator 有两个属性:

属性说明
targetPackage生成实体类存放的包名,一般就是放在该包下
targetProject指定目标项目路径(一个已存在的目录)。
可以是绝对路径或相对路径(如targetProject="src/main/java"),生成的内容会放到指定目录中

在 javaModelGenerator 元素中还可以配置多个 property 子元素,如下:

属性默认值说明
enableSubPackagesfalse如果true,MBG会根据catalogschema来生成子包。
如果false就会直接用targetPackage属性。
immutablefalse该属性用来配置实体类属性是否可变。
如果设置为true,那么会使用构造方法入参,并且不会生成setter方法。
如果为false,实体类属性就可以改变。
trimStringsfalse是否对数据库查询结果进行trim操作
<javamodelgenerator targetpackage="org.dllwh.mybatis.model" targetproject="src\main\java">
    <property name="enableSubPackages" value="true" />
    <property name="trimStrings" value="true" />
</javamodelgenerator>

10.2.3.7 sqlMapGenerator

  可以配置01个,生成SQL Map的xml文件生成器。在MyBatis3之后,可以使用mapper.xml文件 + Mapper接口,或者只使用Mapper接口 + Annotation;所以,如果javaClientGenerator元素中配置了需要生成xml的话,这个元素就必须配置。该元素有targetPackagetargetProject 两个属性

<sqlmapgenerator targetpackage="org.dllwh.dao.impl" targetproject="src/main/java">
    <!-- 针对数据库的一个配置,是否把 schema 作为字包名 -->
    <property name="enableSubPackages" value="false" />
</sqlmapgenerator>
属性说明
targetPackage生成mapper存放的包名,一般就是放在该包下
targetProject指定目标项目路径(一个已存在的目录)。
可以是绝对路径或相对路径(如targetProject="src/main/java"),生成的内容会放到指定目录中

配置示例:

<sqlmapgenerator targetpackage="org.dllwh.mybatis.xml" targetproject="src\main\resources">
    <property name="enableSubPackages" value="true" />
</sqlmapgenerator>

10.2.3.8 javaClientGenerator

  用于配置关于Mapper接口的生成,配置0或1个。注意,如果没有配置该元素,那么默认不会生成Mapper接口。其有 3 个属性:

属性说明
type该属性用于选择一个预定义的客户端代码(可以理解为Mapper接口)生成器,用户可以自定义实现
ANNOTATEDMAPPER:使用Mapper接口+Annotation的方式创建,不会生成对应的XML;
MIXEDMAPPER:使用混合配置,会生成Mapper接口,并适当添加合适的Annotation,但是XML会生成在XML中;
XMLMAPPER:会生成Mapper接口,接口完全依赖XML;
targetPackage生成interface 文件存放的包名,一般就是放在该包下
targetProject指定目标项目路径(一个已存在的目录)。
可以是绝对路径或相对路径(如targetProject="src/main/java"),生成的内容会放到指定目录中

配置示例:

<javaclientgenerator type="XMLMAPPER" targetpackage="org.dllwh.dao" targetproject="src/main/java">

</javaclientgenerator>

10.2.3.9 table

  指定数据库表,要生成哪些表,就写哪些表,要和数据库中对应,不能写错!一个 table 元素对应一张数据库表,如果想同时为多张表生成代码,需要配置多个 table 元素;或者可以将 tableName 设置为 % 来为全部表生成代码。

属性是否必须说明
tableName指定要生成的表名,可以使用SQL通配符匹配多个表。注意:大小写敏感问题
schema×为数据库名,oracle需要配置,mysql不需要配置
catalog×数据库的 catalog
domainObjectName×生成实体对象的类名。如果没有指定,会自动根据表名来生成名称
enableInsert×指定是否生成insert语句,默认true
enableSelectByPrimaryKey×指定是否生成按照主键查询对象的语句(就是getById或get),默认true
enableSelectByExample×指定是否生成动态查询语句,默认true
enableUpdateByPrimaryKey×指定是否生成按照主键update对象的语句,默认true
enableDeleteByPrimaryKey×指定是否生成按照主键delete对象的语句,默认true
enableDeleteByExample×指定是否生成动态delete语句,默认true
enableCountByExample×指定是否生成动态查询总条数语句(用于分页的总条数查询),默认true
enableUpdateByExample×指定是否生成动态修改语句(只修改对象中不为空的属性),默认true
delimitAllColumns×设置是否所有生成的SQL中的列名都使用标识符引起来

此外,table 元素中还可以配置多个 property 和 columnOverride 等子元素。示例代码如下:

<!-- 
    指定是否只生成domain类,如果设置为true,只生成domain类。
    如果还配置了sqlMapGenerator,那么在 mapper.xml 文件中,只生成 resultMap 元素 
-->
<property name="modelOnly" value="false" />

<!-- 可以为生成的类会继承这个类 -->
<!-- <property name="rootClass" value=""/> -->

<!-- 可以为生成的类添加一个父接口 -->
<!-- <property name="rootInterface" value=""/> -->

<!-- 如果设置为true,生成的model类会直接使用column本身的名字,而不会再使用驼峰命名方法 -->
<property name="useActualColumnNames" value="false" />

<!-- 生成主键的方法,如果设置了该元素,会在生成的<insert>元素中生成一条正确的<selectKey>元素 -->
<!-- <generatedKey column="id" sqlStatement="MySql" identity="true"/>-->
<generatedkey column="id" sqlStatement="SELECT LAST_INSERT_ID()" />

<!-- 用来修改表中某个列的属性,MBG 会根据修改后的配置来生成 domain 的属性;
     column:要重新设置的列名;一个 table 元素中可以定义多个 columnOverride 元素哈 -->
<columnoverride column="show_status" javatype="" jdbctype="">
    <!-- 使用 property 属性来指定列要生成的属性名称 -->
    <property name="property" value="showStatus" />

    <!-- javaType 用于指定生成的 domain 的属性类型,使用类型的全限定名-->
    <property name="javaType" value="java.lang.Integer" />

    <!-- jdbcType用于指定该列的JDBC类型
    <property name="jdbcType" value=""/>
    -->
</columnoverride>

10.3 配置示例

下面是一个简单的MyBatis-Generator 配置示例

<!-- 配置文件头 -->
<!--?xml version="1.0" encoding="UTF-8"?-->


<!-- 所有的配置均在根元素 generatorConfiguration 下 -->
<!--配置参考 http://mybatis.org/generator/configreference/xmlconfig.html-->
<generatorconfiguration>
    <!-- 属性配置文件 -->
	<properties resource="mybatis-generator.properties" />

	<context id="MySqlContext" targetruntime="MyBatis3">
		<property name="autoDelimitKeywords" value="true" />
        <!-- 生成的 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" />
		<property name="beginningDelimiter" value="`" />
		<property name="endingDelimiter" value="`" />

		<plugin type="org.mybatis.generator.plugins.SerializablePlugin" />

		<commentgenerator>
			<property name="suppressDate" value="true" />
			<property name="dateFormat" value="yyyy-MM-dd" />
            <!-- 是否去除自动生成的注释 true:是 : false:否 -->
			<property name="suppressAllComments" value="true" />
			<property name="addRemarkComments" value="true" />
		</commentgenerator>

        <!-- 配置数据库连接 -->
		<jdbcconnection driverClass="${spring.datasource.driverClassName}" connectionURL="${spring.datasource.url}" userId="${spring.datasource.username}" password="${spring.datasource.password}" />
        
        <!-- 生成PO类 -->
		<javamodelgenerator targetpackage="${model.target.package}" targetproject="src/main/java">
            <!-- 是否允许子包 -->
            <property name="enableSubPackages" value="false" />
            <!-- 是否对modal添加构造函数 -->
            <property name="constructorBased" value="true" />
            <!-- 是否清理从数据库中查询出的字符串左右两边的空白字符 -->
			<property name="trimStrings" value="true" />
            <!-- 建立modal对象是否不可改变 即生成的modal对象不会有setter方法,只有构造方法 -->
            <property name="immutable" value="false" />
		</javamodelgenerator>

        <!-- 生成 Mapper 接口的位置 -->
		<sqlmapgenerator targetpackage="${mapper.target.package}" targetproject="src/main/java">
            <!-- 针对数据库的一个配置,是否把 schema 作为字包名 -->
            <property name="enableSubPackages" value="false" />
		</sqlmapgenerator>

        <!-- 生成 Mapper XML 的位置 -->
		<javaclientgenerator type="XMLMAPPER" targetpackage="${dao.target.package}" targetproject="src/main/java">
            <!-- 针对 oracle 数据库的一个配置,是否把 schema 作为字包名 -->
            <property name="enableSubPackages" value="false" />
		</javaclientgenerator>

        <!-- 设置数据库的表名和实体类名 -->
		<property name="modelOnly" value="false" /><property name="useActualColumnNames" value="false" /><table tablename="sys_menu" enableinsert="true" enableselectbyprimarykey="true" enableselectbyexample="false" enableupdatebyprimarykey="true" enabledeletebyprimarykey="true" enabledeletebyexample="false" enablecountbyexample="false" enableupdatebyexample="false">
			
            <!-- 如果设置为true,生成的model类会直接使用column本身的名字,而不会再使用驼峰命名方法 -->
			
		</table>
	</context>
</generatorconfiguration>

其中,mybatis-generator.properties 如下:

#Mybatis Generator configuration

# 自定义属性 - 创建人
custom.property.author=独泪了无痕
# 自定义属性 - 创建邮箱
custom.property.email=duleilewuhen@sina.com

# 类根地址
target.prefix=org.dllwh
# 生成实体类地址
model.target.package=org.dllwh.model
# 生成dao接口(mapper)地址
dao.target.package=org.dllwh.dao
# 生成mapper(xml)地址
mapper.target.package=org.dllwh.dao.impl

# 数据库信息
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/spring?useUnicode=true&amp;characterEncoding=UTF-8&amp;useSSL=true
spring.datasource.username=spring
spring.datasource.password=spring

10.4 测试类

使用 Java 代码编程运行,需要按照方式一在Maven的pom文件中引入依赖。然后在项目中新建一个 Java 类,代码类似下面:

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;

public class GeneratorSqlmap {
	public void defaultCommentGenerator() throws Exception {
		// MyBatis-Generator 执行过程中的警告信息
		List<string> warnings = new ArrayList<string>();
		// 当生成的代码重复时,覆盖原代码
		boolean overwrite = true;
		// 指向逆向工程配置文件
		String genCfg = "/generatorConfig.xml";
		// 读取 MyBatis-Generator 配置文件
		File configFile = new File(GeneratorSqlmap.class.getResource(genCfg).getFile());
		// 初始化配置解析器
		ConfigurationParser cp = new ConfigurationParser(warnings);
		// 调用配置解析器创建配置对象
		Configuration config = cp.parseConfiguration(configFile);
		DefaultShellCallback callback = new DefaultShellCallback(overwrite);
		// 创建一个MyBatisGenerator对象。MyBatisGenerator类是真正用来执行生成动作的类
		MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
		// 执行生成代码
		myBatisGenerator.generate(null);

		// 输出警告信息
		warnings.forEach(warning -&gt; System.out.println(warning));
	}

	public static void main(String[] args) throws Exception {
		try {
			GeneratorSqlmap generatorSqlmap = new GeneratorSqlmap();
			generatorSqlmap.defaultCommentGenerator();

		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

10.5 自定义扩展

10.5.1 自定义生成注释

  commentGenerator 生成的是由 org.mybatis.generator.api.CommentGenerator 来控制的,这是一个接口,MyBatis Generator 的默认实现类是 org.mybatis.generator.internal.DefaultCommentGenerator。当你在 generatorConfig.xml 中配置了 commentGenerator 标签,那么默认状态下,生成注释的工作,将由 DefaultCommentGenerator 来完成。 运行 MyBatis-Generator后,查看生成的代码,怎么说呢,数据库注释倒是拿到了,但是生成的一堆其他信息,看着实在是太扎眼了。查看源码,发现这些内容已经写死在DefaultCommentGenerator中了,没有办法自定义。

自己动手丰衣足食,我们为啥不自己写个类实现CommentGenerator接口,然后自定义自己想要的注释呢。观察CommentGenerator接口,发现里面的方法非常多,不仅包含了生成 Java 实体注释对应的方法,还包括了生成XML中注释的方法。所以我们先定义我们自己的注释类CustomSQLCommentGenerator,继承DefaultCommentGenerator,重写我们需要的方法:

  1. 在项目中创建实体类CustomSQLCommentGenerator继承 DefaultCommentGenerato

  2. 配置 generatorConfig.xml设置我们自己的注释生成器:

    <!--?xml version="1.0" encoding="UTF-8"?-->
    
    
    <!-- 所有的配置均在根元素 generatorConfiguration 下 -->
    <generatorconfiguration>
    	<properties resource="mybatis-generator.properties" />
    
    	<context id="MySqlContext" targetruntime="MyBatis3">
    		<!-- 自定义comment生成器地址 -->
    		<commentgenerator type="xx.xx.CustomSQLCommentGenerator">
    		</commentgenerator>
    	</context>
    </generatorconfiguration>
    
  3. 再次运行主类 MyBatis-Generator,成功的生成了类注释和字段注释~

  4. 还有一点儿需要补充的,上面的示例是继承了 DefaultCommentGenerator 实现的,也可以通过实现CommentGenerator 接口实现。

    package org.dllwh.template.database.mybatis.custom;
    
    import static org.mybatis.generator.internal.util.StringUtility.*;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.List;
    import java.util.Properties;
    import org.mybatis.generator.api.*;
    import org.mybatis.generator.api.dom.java.*;
    import org.mybatis.generator.api.dom.xml.XmlElement;
    import org.mybatis.generator.config.MergeConstants;
    
    public class CustomSQLCommentGenerator implements CommentGenerator {
    	/** 属性,即配置在 commentGenerator 标签之内的 Property 标签 */
    	private Properties properties;
    	/** 生成的注释中是否不包含时间信息,默认为false */
    	private boolean suppressDate;
    	/** 是否去除自动生成的注释 */
    	private boolean suppressAllComments;
    	/** 是否添加数据库内的注释 */
    	private boolean addRemarkComments;
    	/** 生成的注释中,时间的显示格式 */
    	private SimpleDateFormat dateFormat;
    	/** 自定义属性 - 创建人 */
    	private String author;
    	/** 自定义属性 - 创建邮箱 */
    	private String email;
    	/** 自定义属性 - 版本 */
    	private String version;
    	/** 自定义属性 - 是否添加get注释 */
    	private boolean addGetComments;
    	/** 自定义属性 - 是否添加set注释 */
    	private boolean addSetComments;
    
    	public CustomSQLCommentGenerator() {
    		super();
    		properties = new Properties();
    		suppressDate = false;
    		suppressAllComments = false;
    		addRemarkComments = true;
    	}
    
    	/**
    	 * 从该配置中的任何属性添加此实例的属性CommentGenerator配置,这个方法将在任何其他方法之前被调用。
    	 */
    	@Override
    	public void addConfigurationProperties(Properties properties) {
    		// 获取自定义的 properties
    		this.properties.putAll(properties);
    
    		author = properties.getProperty("author", "");
    		email = properties.getProperty("email", "");
    		version = properties.getProperty("version", "V 1.0.1");
    		addGetComments = isTrue(properties.getProperty("addGetComments")) ? true : false;
    		addSetComments = isTrue(properties.getProperty("addSetComments")) ? true : false;
    
    		String dateFormatString = properties.getProperty("dateFormat", "yyyy-MM-dd HH:mm:ss");
    		if (stringHasValue(dateFormatString)) {
    			dateFormat = new SimpleDateFormat(dateFormatString);
    		}
    	}
    
    	/**
    	 * 生成xx.java文件(model)属性的注释,注释为空就不给属性添加。
    	 */
    	@Override
    	public void addFieldComment(Field field, IntrospectedTable introspectedTable,
    			IntrospectedColumn introspectedColumn) {
    		if (suppressAllComments) {
    			return;
    		}
    		// 获取列注释
    		String remarks = introspectedColumn.getRemarks();
    
    		// 开启注释,并且数据库中comment有值
    		if (addRemarkComments &amp;&amp; stringHasValue(remarks)) {
    			// 通过换行符分割
    			String[] remarkLines = remarks.split(System.getProperty("line.separator"));
    			int length = remarkLines.length;
    			// 如果有多行,就换行显示
    			if (length &gt; 1) {
    				// 注释开始的地方
    				field.addJavaDocLine("/**");
    				for (int i = 0; i &lt; length; i++) {
    					field.addJavaDocLine(" * " + remarkLines[i]);
    				}
    				// 注释结束
    				field.addJavaDocLine(" */");
    			} else {
    				field.addJavaDocLine("/** " + remarks + " */");
    			}
    		}
    	}
    
    	/**
    	 * 实体类的静态字段,为空就不给属性添加。
    	 */
    	@Override
    	public void addFieldComment(Field field, IntrospectedTable introspectedTable) {
    		if (suppressAllComments) {
    			return;
    		}
    	}
    
    	/**
    	 * 创建的数据表对应的类添加的注释
    	 */
    	@Override
    	public void addModelClassComment(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
    		if (suppressAllComments || !addRemarkComments) {
    			return;
    		}
    		topLevelClass.addJavaDocLine("/**");
    		topLevelClass.addJavaDocLine(" * 把今天最好的表现当作明天最新的起点..~");
    		topLevelClass.addJavaDocLine(" * ");
    		topLevelClass.addJavaDocLine(" * Today the best performance as tomorrow newest starter!");
    		topLevelClass.addJavaDocLine(" * ");
    		topLevelClass.addJavaDocLine(" * @类描述 : TODO(这里用一句话描述这个类的作用)");
    
    		// 数据库表名
    		String tableName = introspectedTable.getFullyQualifiedTableNameAtRuntime();
    		// 获取表注释
    		String tableRemarks = introspectedTable.getRemarks();
    
    		topLevelClass.addJavaDocLine(" * ");
    		topLevelClass.addJavaDocLine(" * @数据表 : " + tableName);
    
    		if (stringHasValue(tableRemarks)) {
    			topLevelClass.addJavaDocLine(" * ");
    			topLevelClass.addJavaDocLine(" * @数据表注释 : ");
    			String[] remarkLines = tableRemarks.split(System.getProperty("line.separator"));
    			for (String remarkLine : remarkLines) {
    				topLevelClass.addJavaDocLine(" * " + remarkLine);
    			}
    		}
    		topLevelClass.addJavaDocLine(" * ");
    
    		if (stringHasValue(email) &amp;&amp; stringHasValue(author)) {
    			topLevelClass.addJavaDocLine(" * @author : <a href="\&quot;mailto:&quot;" + email "\"> " + author + "</a>");
    		} else if (stringHasValue(author) &amp;&amp; !stringHasValue(email)) {
    			topLevelClass.addJavaDocLine(" * @author : " + author);
    		} else if (stringHasValue(email) &amp;&amp; !stringHasValue(author)) {
    			topLevelClass.addJavaDocLine(" * @email : " + email);
    		}
    
    		topLevelClass.addJavaDocLine(" * @创建时间 : " + getDateString());
    		topLevelClass.addJavaDocLine(" * @版本 : " + version);
    		topLevelClass.addJavaDocLine(" * @since : " + System.getProperty("java.version"));
    		topLevelClass.addJavaDocLine(" * @see <a href="\&quot;\&quot;">TODO(连接内容简介)</a>");
    		topLevelClass.addJavaDocLine(" */");
    	}
    
    	/**
    	 * Java类的类注释
    	 */
    	@Override
    	public void addClassComment(InnerClass innerClass, IntrospectedTable introspectedTable) {
    		if (suppressAllComments) {
    			return;
    		}
    	}
    
    	/**
    	 * Java类的类注释
    	 */
    	@Override
    	public void addClassComment(InnerClass innerClass, IntrospectedTable introspectedTable, boolean markAsDoNotDelete) {
    		if (suppressAllComments) {
    			return;
    		}
    	}
    
    	/**
    	 * 为枚举添加注释
    	 */
    	@Override
    	public void addEnumComment(InnerEnum innerEnum, IntrospectedTable introspectedTable) {
    		if (suppressAllComments) {
    			return;
    		}
    		StringBuilder sb = new StringBuilder();
    		innerEnum.addJavaDocLine("/**");
    		sb.append(introspectedTable.getFullyQualifiedTable());
    		innerEnum.addJavaDocLine(sb.toString());
    		addJavadocTag(innerEnum, false);
    		innerEnum.addJavaDocLine(" */");
    	}
    
    	/**
    	 * 数据库对应实体类的Getter方法注解
    	 */
    	@Override
    	public void addGetterComment(Method method, IntrospectedTable introspectedTable,
    			IntrospectedColumn introspectedColumn) {
    		if (suppressAllComments || !addGetComments) {
    			return;
    		}
    		method.addJavaDocLine("/**");
    
    		StringBuilder sb = new StringBuilder();
    		sb.append(" * ");
    		if (stringHasValue(introspectedColumn.getRemarks())) {
    			sb.append(introspectedColumn.getRemarks());
    			method.addJavaDocLine(sb.toString());
    			method.addJavaDocLine(" *");
    		}
    
    		sb.setLength(0);
    		sb.append(" * @return ");
    		sb.append(introspectedColumn.getActualColumnName());
    
    		if (stringHasValue(introspectedColumn.getRemarks())) {
    			sb.append(" - ");
    			sb.append(introspectedColumn.getRemarks());
    
    		}
    		method.addJavaDocLine(sb.toString());
    		method.addJavaDocLine(" */");
    		return;
    	}
    
    	/**
    	 * 数据库对应实体类的Setter方法注解
    	 */
    	@Override
    	public void addSetterComment(Method method, IntrospectedTable introspectedTable,
    			IntrospectedColumn introspectedColumn) {
    		if (suppressAllComments || !addSetComments) {
    			return;
    		}
    		method.addJavaDocLine("/**");
    		StringBuilder sb = new StringBuilder();
    		if (stringHasValue(introspectedColumn.getRemarks())) {
    			sb.append(" * ");
    			sb.append(introspectedColumn.getRemarks());
    			method.addJavaDocLine(sb.toString());
    			method.addJavaDocLine(" *");
    		}
    
    		Parameter parm = method.getParameters().get(0);
    		sb.setLength(0);
    		sb.append(" * @param ");
    		sb.append(parm.getName());
    		if (stringHasValue(introspectedColumn.getRemarks())) {
    			sb.append(" ");
    			sb.append(introspectedColumn.getRemarks());
    		}
    		method.addJavaDocLine(sb.toString());
    		method.addJavaDocLine(" */");
    	}
    
    	/**
    	 * 普通方法的注释,这里主要是XXXMapper.java里面的接口方法的注释
    	 */
    	@Override
    	public void addGeneralMethodComment(Method method, IntrospectedTable introspectedTable) {
    		if (suppressAllComments) {
    			return;
    		}
    		method.addJavaDocLine("/**");
    		method.addJavaDocLine(" * " + method.getName());
    		method.addJavaDocLine(" * ");
    		List<parameter> parameters = method.getParameters();
    		parameters.forEach(parameter -&gt; method.addJavaDocLine(" * @param " + parameter.getName()));
    		method.addJavaDocLine(" * ");
    		// 如果有返回类型,添加@return
    		String returnType = "void";
    
    		if (method.getReturnType() != null &amp;&amp; !returnType.equals(method.getReturnType().toString())) {
    			method.addJavaDocLine(" * @return ");
    		}
    		// addJavadocTag(method, false);
    		method.addJavaDocLine(" */");
    	}
    
    	/**
    	 * 给Java文件加注释,这个注释是在文件的顶部,也就是package上面。
    	 */
    	@Override
    	public void addJavaFileComment(CompilationUnit compilationUnit) {
    		compilationUnit.addFileCommentLine("/*");
    		compilationUnit.addFileCommentLine("*");
    		compilationUnit.addFileCommentLine("* " + compilationUnit.getType().getShortName() + ".java");
    		compilationUnit.addFileCommentLine("* Copyright(C) 2017-2020 xxx公司");
    		compilationUnit.addFileCommentLine("* ALL rights reserved.");
    		compilationUnit.addFileCommentLine("* @date " + getDateString() + "");
    		compilationUnit.addFileCommentLine("*/");
    	}
    
    	/**
    	 * 实体类对应的mapper.xml注释,mapper类不加注释,如有需要参考 DefaultCommentGenerator
    	 */
    	@Override
    	public void addComment(XmlElement xmlElement) {
    		if (suppressAllComments) {
    			return;
    		}
    	}
    
    	/**
    	 * 为调用此方法作为根元素的第一个子节点添加注释。
    	 */
    	@Override
    	public void addRootComment(XmlElement rootElement) {
    
    	}
    
    	/**
    	 * @方法描述 : 返回格式化的日期字符串以包含在Javadoc标记中和XML注释。 如果您不想要日期,则可以返回null在这些文档元素中。
    	 * @return 格式化后的日期
    	 */
    	protected String getDateString() {
    		if (suppressDate) {
    			return null;
    		} else if (dateFormat != null) {
    			return dateFormat.format(new Date());
    		} else {
    			return new Date().toString();
    		}
    	}
    
    	/**
    	 * @方法描述: 此方法为其添加了自定义javadoc标签。
    	 *
    	 * @param javaElement
    	 * @param markAsDoNotDelete
    	 */
    	protected void addJavadocTag(JavaElement javaElement, boolean markAsDoNotDelete) {
    		javaElement.addJavaDocLine(" *");
    		StringBuilder sb = new StringBuilder();
    		sb.append(" * ");
    		sb.append(MergeConstants.NEW_ELEMENT_TAG);
    		if (markAsDoNotDelete) {
    			sb.append(" do_not_delete_during_merge");
    		}
    		String s = getDateString();
    		if (s != null) {
    			sb.append(' ');
    			sb.append(s);
    		}
    		javaElement.addJavaDocLine(sb.toString());
    	}
    }
    

10.5.2 修改Mapper文件名

import static org.mybatis.generator.internal.util.StringUtility.stringHasValue;
import static org.mybatis.generator.internal.util.messages.Messages.getString;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;

public class RenameJavaMapperPlugins extends PluginAdapter {
	private String searchString;
	private String replaceString;
	private Pattern pattern;

	public boolean validate(List<string> warnings) {

		searchString = properties.getProperty("searchString");
		replaceString = properties.getProperty("replaceString");

		boolean valid = stringHasValue(searchString) &amp;&amp; stringHasValue(replaceString);

		if (valid) {
			pattern = Pattern.compile(searchString);
		} else {
			if (!stringHasValue(searchString)) {
				warnings.add(getString("ValidationError.18", "RenameExampleClassPlugin", "searchString"));
			}
			if (!stringHasValue(replaceString)) {
				warnings.add(getString("ValidationError.18", "RenameExampleClassPlugin", "replaceString"));
			}
		}

		return valid;
	}

	@Override
	public void initialized(IntrospectedTable introspectedTable) {
		String oldType = introspectedTable.getMyBatis3JavaMapperType();
		Matcher matcher = pattern.matcher(oldType);
		oldType = matcher.replaceAll(replaceString);

		introspectedTable.setMyBatis3JavaMapperType(oldType);
	}
}

10.5.3 自定义的lombok配置

// 在类上添加注解
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @Builder
    public class CustomLombokPluginAviationInfo {
    }
// 在时间字段上自动添加注解
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date endTime;
import static org.mybatis.generator.internal.util.StringUtility.stringHasValue;
import static org.mybatis.generator.internal.util.messages.Messages.getString;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Properties;
import org.apache.commons.lang3.StringUtils;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.Plugin;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.java.Field;
import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
import org.mybatis.generator.api.dom.java.Interface;
import org.mybatis.generator.api.dom.java.Method;
import org.mybatis.generator.api.dom.java.TopLevelClass;

public class CustomLombokPlugin extends PluginAdapter {
	private final Collection<annotations> annotations;
	/** 继承的父类 */
	private String supperClass;
	/** 过滤的属性字段 */
	private String ignoreFields;
	/** 自定义属性 - 创建人 */
	private String author;
	/** 自定义属性 - 创建邮箱 */
	private String email;
	/** 自定义属性 - 版本 */
	private String version;

	public CustomLombokPlugin() {
		annotations = new LinkedHashSet&lt;&gt;(Annotations.values().length);
	}

	@Override
	public boolean validate(List<string> warnings) {
		boolean valid = true;
		supperClass = properties.getProperty("supperClass");
		ignoreFields = properties.getProperty("ignoreFields");
		author = properties.getProperty("author", "");
		email = properties.getProperty("email", "");
		version = properties.getProperty("version", "V 1.0.1");

		try {
			Class.forName(supperClass);
		} catch (ClassNotFoundException e) {
			warnings.add(getString("ValidationError.18", "CustomLombokPlugin", "supperClass"));
		}
		return valid;
	}

	/**
	 * 获取表
	 */
	@Override
	public boolean modelBaseRecordClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
		addAnnotations(topLevelClass);
		return true;
	}

	@Override
	public boolean modelPrimaryKeyClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
		addAnnotations(topLevelClass);
		return true;
	}

	@Override
	public boolean modelRecordWithBLOBsClassGenerated(TopLevelClass topLevelClass,
			IntrospectedTable introspectedTable) {
		addAnnotations(topLevelClass);
		return true;
	}

	/**
	 * 设置get方法(使用lombok不需要,直接返回false)
	 */
	@Override
	public boolean modelGetterMethodGenerated(Method method, TopLevelClass topLevelClass,
			IntrospectedColumn introspectedColumn, IntrospectedTable introspectedTable, ModelClassType modelClassType) {
		return false;
	}

	/**
	 * 设置set方法(使用lombok不需要,直接返回false)
	 */
	@Override
	public boolean modelSetterMethodGenerated(Method method, TopLevelClass topLevelClass,
			IntrospectedColumn introspectedColumn, IntrospectedTable introspectedTable, ModelClassType modelClassType) {
		return false;
	}

	/**
	 * 设置lombok注解 <br>
	 */
	private void addAnnotations(TopLevelClass topLevelClass) {
		for (Annotations annotation : annotations) {
			// 添加domain的import
			topLevelClass.addImportedType(annotation.javaType);
			// 添加domain的注解
			topLevelClass.addAnnotation(annotation.asAnnotation());
		}

		/**
		 * 设置父类
		 */
		if (supperClass != null) {
			FullyQualifiedJavaType fullyQualifiedJavaType = new FullyQualifiedJavaType(supperClass);
			topLevelClass.addImportedType("lombok.EqualsAndHashCode");
			topLevelClass.addImportedType(fullyQualifiedJavaType.getFullyQualifiedName());
			topLevelClass.addAnnotation("@EqualsAndHashCode(callSuper = false)");
			topLevelClass.setSuperClass(fullyQualifiedJavaType.getShortName());
		}

		/**
		 * 将需要忽略生成的属性过滤掉
		 */
		List<field> fields = topLevelClass.getFields();
		if (null != ignoreFields &amp;&amp; !"".equals(ignoreFields)) {
			String[] field = ignoreFields.split(",");
			for (String ignoreField : field) {
				for (int i = 0; i &lt; fields.size(); i++) {
					Field tableField = fields.get(i);
					if (ignoreField.equalsIgnoreCase(tableField.getName())) {
						fields.remove(tableField);
						i--;
					}
				}
			}
		}
	}

	/**
	 * entity类设置
	 * 
	 * @param properties
	 */
	@Override
	public void setProperties(Properties properties) {
		super.setProperties(properties);

		// @Data is default annotation
		annotations.add(Annotations.DATA);
		annotations.add(Annotations.ALL_ARGS_CONSTRUCTOR);
		annotations.add(Annotations.NO_ARGS_CONSTRUCTOR);
		annotations.add(Annotations.BUILDER);

		for (String annotationName : properties.stringPropertyNames()) {
			if (annotationName.contains(".")) {
				continue;
			}
			String value = properties.getProperty(annotationName);
			if (!Boolean.parseBoolean(value)) {
				// The annotation is disabled, skip it
				continue;
			}
			Annotations annotation = Annotations.getValueOf(annotationName);
			if (annotation == null) {
				continue;
			}
			String optionsPrefix = annotationName + ".";
			for (String propertyName : properties.stringPropertyNames()) {
				if (!propertyName.startsWith(optionsPrefix)) {
					// A property not related to this annotation
					continue;
				}
				String propertyValue = properties.getProperty(propertyName);
				annotation.appendOptions(propertyName, propertyValue);
				annotations.add(annotation);
				annotations.addAll(Annotations.getDependencies(annotation));
			}
		}
	}

	/**
	 * mapper类设置注解以及Mapper文件的注释
	 */
	@Override
	public boolean clientGenerated(Interface interfaze, TopLevelClass topLevelClass,
			IntrospectedTable introspectedTable) {

		interfaze.addJavaDocLine("/**");
		interfaze.addJavaDocLine(" * 把今天最好的表现当作明天最新的起点..~");
		interfaze.addJavaDocLine(" * ");
		interfaze.addJavaDocLine(" * Today the best performance as tomorrow newest starter!");
		interfaze.addJavaDocLine(" * ");
		interfaze.addJavaDocLine(" * @类描述 : TODO(这里用一句话描述这个类的作用)");

		// 获取表注释
		String tableRemarks = introspectedTable.getRemarks();

		if (stringHasValue(tableRemarks)) {
			interfaze.addJavaDocLine(" * ");
			interfaze.addJavaDocLine(" * @数据表注释 : ");
			String[] remarkLines = tableRemarks.split(System.getProperty("line.separator"));
			for (String remarkLine : remarkLines) {
				interfaze.addJavaDocLine(" * " + remarkLine);
			}
		}
		if (stringHasValue(tableRemarks)) {
			interfaze.addJavaDocLine(" * ");
			interfaze.addJavaDocLine(" * @数据表注释 : ");
			String[] remarkLines = tableRemarks.split(System.getProperty("line.separator"));
			for (String remarkLine : remarkLines) {
				interfaze.addJavaDocLine(" * " + remarkLine);
			}
		}
		interfaze.addJavaDocLine(" * ");

		if (stringHasValue(email) &amp;&amp; stringHasValue(author)) {
			interfaze.addJavaDocLine(" * @author : <a href="\&quot;mailto:&quot;" + email "\"> " + author + "</a>");
		} else if (stringHasValue(author) &amp;&amp; StringUtils.isBlank(email)) {
			interfaze.addJavaDocLine(" * @author : " + author);
		}

		// interfaze.addJavaDocLine(" * @创建时间 : " + getDateString());
		interfaze.addJavaDocLine(" * @版本 : " + version);
		interfaze.addJavaDocLine(" * @since : " + System.getProperty("java.version"));

		interfaze.addJavaDocLine(" * @see <a href="\&quot;\&quot;">TODO(连接内容简介)</a>");
		interfaze.addJavaDocLine(" */");

		interfaze.addImportedType(new FullyQualifiedJavaType("org.apache.ibatis.annotations.Mapper"));
		interfaze.addAnnotation("@Mapper");
		return true;
	}

	/**
	 * entity字段设置
	 */
	@Override
	public boolean modelFieldGenerated(Field field, TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn,
			IntrospectedTable introspectedTable, Plugin.ModelClassType modelClassType) {
		if (field.getType().getShortNameWithoutTypeArguments().equals("Date")) {
			field.getAnnotations().add(Annotations.DATE_TIME_FORMAT.asAnnotation());
			field.getAnnotations().add(Annotations.JSON_FORMAT.asAnnotation());
			topLevelClass.addImportedType(Annotations.DATE_TIME_FORMAT.javaType);
			topLevelClass.addImportedType(Annotations.JSON_FORMAT.javaType);
		}
		return true;
	}

	enum Annotations {

		DATA("data", "@Data", "lombok.Data"), BUILDER("builder", "@Builder", "lombok.Builder"),
		ALL_ARGS_CONSTRUCTOR("allArgsConstructor", "@AllArgsConstructor", "lombok.AllArgsConstructor"),
		NO_ARGS_CONSTRUCTOR("noArgsConstructor", "@NoArgsConstructor", "lombok.NoArgsConstructor"),
		ACCESSORS("accessors", "@Accessors", "lombok.experimental.Accessors"),
		TO_STRING("toString", "@ToString", "lombok.ToString"),
		DATE_TIME_FORMAT("dateTimeFormat", "@DateTimeFormat(pattern = \"yyyy-MM-dd HH:mm:ss\")",
				"org.springframework.format.annotation.DateTimeFormat"),
		JSON_FORMAT("jsonFormat", "@JsonFormat(pattern = \"yyyy-MM-dd HH:mm:ss\")",
				"com.fasterxml.jackson.annotation.JsonFormat");

		private final String paramName;
		private final String name;
		private final FullyQualifiedJavaType javaType;
		private final List<string> options;

		Annotations(String paramName, String name, String className) {
			this.paramName = paramName;
			this.name = name;
			this.javaType = new FullyQualifiedJavaType(className);
			this.options = new ArrayList<string>();
		}

		public static Annotations getValueOf(String paramName) {
			for (Annotations annotation : Annotations.values()) {
				if (String.CASE_INSENSITIVE_ORDER.compare(paramName, annotation.paramName) == 0) {
					return annotation;
				}
			}

			return null;
		}

		public static Collection<annotations> getDependencies(Annotations annotation) {
			if (annotation == ALL_ARGS_CONSTRUCTOR) {
				return Collections.singleton(NO_ARGS_CONSTRUCTOR);
			} else {
				return Collections.emptyList();
			}
		}

		// A trivial quoting.
		// Because Lombok annotation options type is almost String or boolean.
		private static String quote(String value) {
			if (Boolean.TRUE.toString().equals(value) || Boolean.FALSE.toString().equals(value))
			// case of boolean, not passed as an array.
			{
				return value;
			}
			return value.replaceAll("[\\w]+", "\"$0\"");
		}

		public void appendOptions(String key, String value) {
			String keyPart = key.substring(key.indexOf(".") + 1);
			String valuePart = value.contains(",") ? String.format("{%s}", value) : value;
			this.options.add(String.format("%s=%s", keyPart, quote(valuePart)));
		}

		public String asAnnotation() {
			if (options.isEmpty()) {
				return name;
			}
			StringBuilder sb = new StringBuilder();
			sb.append(name);
			sb.append("(");
			boolean first = true;
			for (String option : options) {
				if (first) {
					first = false;
				} else {
					sb.append(", ");
				}
				sb.append(option);
			}
			sb.append(")");
			return sb.toString();
		}
	}
}

10.5.4 自定义的生成配置

<!--?xml version="1.0" encoding="UTF-8"?-->

<!-- 所有的配置均在根元素 generatorConfiguration 下 -->
<generatorconfiguration>
	<properties resource="mybatis-generator.properties" />

	<context id="MySqlContext" targetruntime="MyBatis3">
		<property name="autoDelimitKeywords" value="true" />
		<!-- 生成的 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" />
		<property name="beginningDelimiter" value="`" />
		<property name="endingDelimiter" value="`" />

		<plugin type="org.mybatis.generator.plugins.SerializablePlugin" />

		<!-- 自定义lomBok插件 -->
		<plugin type="org.dllwh.template.database.mybatis.custom.CustomLombokPlugin">
			<property name="defaultSerialVersionUID" value="true" />
			<property name="supperClass" value="" />
			<property name="ignoreFields" value="" />
			<property name="author" value="${custom.property.author}" />
			<property name="email" value="${custom.property.email}" />
			<property name="version" value="V 1.0.1" />
		</plugin>
		
		<!-- 自定义JavaMapper文件名 -->
		<plugin type="org.dllwh.template.database.mybatis.custom.RenameJavaMapperPlugins">
			<property name="searchString" value="Mapper$" />
			<property name="replaceString" value="Dao" />
		</plugin>
 
		<!-- 自定义comment生成器地址 -->
		<commentgenerator type="org.dllwh.template.database.mybatis.custom.CustomSQLCommentGenerator">
			<property name="author" value="${custom.property.author}" />
			<property name="email" value="${custom.property.email}" />
			<property name="version" value="V 1.0.1" />
			<property name="addGetComments" value="false" />
			<property name="addSetComments" value="false" />
		</commentgenerator>

		<!-- 配置数据库连接 -->
		<jdbcconnection driverClass="${spring.datasource.driverClassName}" connectionURL="${spring.datasource.url}" userId="${spring.datasource.username}" password="${spring.datasource.password}" />

		<!-- 生成实体的位置 -->
		<javamodelgenerator targetpackage="${model.target.package}" targetproject="src/main/java">
			<property name="trimStrings" value="true" />
		</javamodelgenerator>

		<!-- 生成 Mapper 接口的位置 -->
		<sqlmapgenerator targetpackage="${mapper.target.package}" targetproject="src/main/java">
		</sqlmapgenerator>
		
		<!-- 生成 Mapper XML 的位置 -->
		<javaclientgenerator type="XMLMAPPER" targetpackage="${dao.target.package}" targetproject="src/main/java">
		</javaclientgenerator>
		
		<!-- 设置数据库的表名和实体类名 -->
		<property name="modelOnly" value="false" /><property name="useActualColumnNames" value="false" /><columnoverride column="excep_detail" javaType="java.lang.String" jdbcType="text" /><columnoverride column="parameter" javaType="java.lang.String" jdbcType="text" /><columnoverride column="result" javaType="java.lang.String" jdbcType="text" /><table tablename="sys__operate_log" enableinsert="true" enableselectbyprimarykey="true" enableselectbyexample="false" enableupdatebyprimarykey="true" enabledeletebyprimarykey="true" enabledeletebyexample="false" enablecountbyexample="false" enableupdatebyexample="false">
			
			<!-- 如果设置为true,生成的model类会直接使用column本身的名字,而不会再使用驼峰命名方法 -->
			
			<!-- -->
			
			
			
		</table>
	</context>
</generatorconfiguration>
```</annotations></string></string></field></string></annotations></string></parameter></string></string>