1. 什么是MyBatis Generator?

MyBatis Generator 是 MyBatis 提供的一个代码生成工具。可以帮我们生成 表对应的持久化对象(po)、操作数据库的接口(dao)、CRUD sql的xml(mapper)。

集成MyBatis Generator前提是,springboot项目中已经集成了MyBatis。至于如何集成mybatis,请查看: SpringBoot学习(三):集成Mybatis

2. 添加插件

修改pom.xml文件,添加编译插件

<build>
<plugins>
...
<!-- ++++++++++++++++++++ mybatis代码生成器插件-开始部分 ++++++++++++++++++++ -->
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.7</version>
<configuration>
<!-- mybatis的代码生成器的配置文件 -->
<configurationFile>src/main/resources/mybatis-generator/config.xml</configurationFile>
<!--允许覆盖生成的文件-->
<overwrite>true</overwrite>
<!--verbose:true是为了运行mvn mybatis-generator:generate -e时显示具体过程。-->
<verbose>true</verbose>
</configuration>
<dependencies>
<!-- mysql的JDBC驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
</dependencies>
</plugin>
<!-- ++++++++++++++++++++ mybatis代码生成器插件-结束部分 ++++++++++++++++++++ -->
</plugins>
</build>

配置说明:

  • configurationFile: mybatis的代码生成器的配置文件

  • overwrite : 允许覆盖生成的文件,需要注意的是: MyBatis Generator 只会覆盖旧的 po、dao,对于 *mapper.xml 不会覆盖,而是追加,这样做的目的是防止用户自己写的 sql 语句一不小心都被 MyBatis Generator 给覆盖了。

  • verbose: 当设置true时,控制台会输出mvn mybatis-generator:generate -e具体过程

3. 添加配置

3.1 MyBatis Generator 生成器配置

MyBatis Generator 插件启动后,会根据你在 pom.xml 中配置的路径(src/main/resources/mybatis-generator/config.xml)找到该配置文件。这个配置文件才是详细都配置 MyBatis Generator 生成代码的各种细节。

config.xml配置详情

<?xml version="1.0" encoding="UTF-8" ?>
<!--mybatis的代码生成器相关配置-->
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

<generatorConfiguration>
<!-- 引入配置文件 -->
<!-- 配置文件在: /src/main/resources/mybatis-generator/generatorjdbc.properties -->
<properties resource="mybatis-generator/generatorjdbc.properties"/>
<!--
1.一个数据库一个context
2.context的子元素必须按照它给出的顺序:
property*,plugin*,commentGenerator?,jdbcConnection,javaTypeResolver?,
javaModelGenerator,sqlMapGenerator?,javaClientGenerator?,table+
-->
<!--
id : 随便填,保证多个 context id 不重复就行
defaultModelType : 可以不填,默认值 conditional,flat表示一张表对应一个po
targetRuntime:可以不填,默认值 MyBatis3,常用的还有 MyBatis3Simple,这个配置会影响生成的 dao 和 mapper.xml的内容
-->
<context id="myContext" targetRuntime="MyBatis3" defaultModelType="flat">

<!-- 自动识别数据库关键字,默认false,如果设置为true,根据SqlReservedWords中定义的关键字列表;
一般保留默认值,遇到数据库关键字(Java关键字),使用columnOverride覆盖 -->
<property name="autoDelimitKeywords" value="true"/>

<!-- 生成的Java文件的编码 -->
<property name="javaFileEncoding" value="utf-8"/>

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

<!-- 格式化java代码 -->
<property name="javaFormatter" value="org.mybatis.generator.api.dom.DefaultJavaFormatter"/>
<!-- 格式化XML代码 -->
<property name="xmlFormatter" value="org.mybatis.generator.api.dom.DefaultXmlFormatter"/>

<!-- ******************* 插件开始部分 *****************-->
<!-- JavaBean 实现 序列化 接口 -->
<plugin type="org.mybatis.generator.plugins.SerializablePlugin"/>
<!-- generator 时,为类生成toString -->
<plugin type="org.mybatis.generator.plugins.ToStringPlugin"/>

<!-- 提供clientSuffix、exampleSuffix、modelSuffix来修改对应生成的类和文件的结尾 -->
<plugin type="com.itfsw.mybatis.generator.plugins.TableRenameConfigurationPlugin">
<!-- TbMapper -> TbDao, TbMapper.xml -> TbDao.xml -->
<property name="clientSuffix" value="Dao"/>
<!-- 发现如果使用这个修改example后缀后,指定example类目录的插件就会失效-->
<!-- <property name="exampleSuffix" value="Query"/>-->
<!-- 实体类添加后缀-->
<property name="modelSuffix" value="Model"/>
</plugin>

<!-- Table重命名插件 -->
<!-- 去掉表前缀,解决:micro_user_information 去除后生成 UserinformationModel问题-->
<plugin type="com.itfsw.mybatis.generator.plugins.TableRenamePlugin">
<!-- 可根据具体需求确定是否配置 -->
<property name="searchString" value="^Micro"/>
<property name="replaceString" value=""/>
</plugin>

<!-- Example 目标包修改插件 -->
<plugin type="com.itfsw.mybatis.generator.plugins.ExampleTargetPlugin">
<!-- 修改Example类生成到目标包下 -->
<property name="targetPackage" value="com.hui.javalearn.dao.example"/>
</plugin>


<!-- 自定义注释插件 -->
<plugin type="com.itfsw.mybatis.generator.plugins.CommentPlugin">
<!-- 自定义模板路径 -->
<property name="template" value="${mybatis.comment.file}"/>
</plugin>
<!-- Lombok插件 去除模型中的get和set ,用@Data注解取代 -->
<plugin type="com.itfsw.mybatis.generator.plugins.LombokPlugin">
<!-- @Data 默认开启,同时插件会对子类自动附加@EqualsAndHashCode(callSuper = true),@ToString(callSuper = true) -->
<property name="@Data" value="true"/>
<!-- @Builder 必须在 Lombok 版本 >= 1.18.2 的情况下开启,对存在继承关系的类自动替换成@SuperBuilder -->
<property name="@Builder" value="false"/>
<!-- @NoArgsConstructor 和 @AllArgsConstructor 使用规则和Lombok一致 -->
<property name="@AllArgsConstructor" value="false"/>
<property name="@NoArgsConstructor" value="false"/>
<!-- @Getter、@Setter、@Accessors 等使用规则参见官方文档 -->
<property name="@Accessors(chain = true)" value="false"/>
<!-- 临时解决IDEA工具对@SuperBuilder的不支持问题,开启后(默认未开启)插件在遇到@SuperBuilder注解时会调用ModelBuilderPlugin来生成相应的builder代码 -->
<property name="supportSuperBuilderForIdea" value="false"/>
</plugin>
<!-- ************* 插件结束部分 ****************-->


<!-- 注释 -->
<commentGenerator>
<!-- 是否取消注释 true:否 false:是 -->
<property name="suppressAllComments" value="false"/>
<!-- 是否生成注释代时间戳 -->
<property name="suppressDate" value="false"/>
<!-- 生成时间的格式-->
<property name="dateFormat" value="yyyy-MM-dd HH:mm:ss "/>
<!-- 是否带上数据库字段备注信息,只有suppressAllComments为false时才生效-->
<property name="addRemarkComments" value="true"/>
</commentGenerator>


<!-- jdbc连接 -->
<jdbcConnection driverClass="${spring.datasource.driverClassName}"
connectionURL="${spring.datasource.url}"
userId="${spring.datasource.username}"
password="${spring.datasource.password}">
<!--高版本的 mysql-connector-java 需要设置 nullCatalogMeansCurrent=true-->
<property name="nullCatalogMeansCurrent" value="true"/>
</jdbcConnection>

<!-- 类型转换 -->
<javaTypeResolver>
<!--是否使用bigDecimal,默认false。
false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer
true,把JDBC DECIMAL 和 NUMERIC 类型解析为java.math.BigDecimal-->
<property name="forceBigDecimals" value="true"/>
<!--是否使用转换日期,默认false
false,将所有 JDBC 的时间类型解析为 java.util.Date
true,将 JDBC 的时间类型按如下规则解析
DATE -> java.time.LocalDate
TIME -> java.time.LocalTime
TIMESTAMP -> java.time.LocalDateTime
TIME_WITH_TIMEZONE -> java.time.OffsetTime
TIMESTAMP_WITH_TIMEZONE -> java.time.OffsetDateTime
-->
<!--<property name="useJSR310Types" value="false"/>-->
</javaTypeResolver>

<!-- 生成实体类地址 -->
<javaModelGenerator targetPackage="com.hui.javalearn.model" targetProject="src/main/java">
<!-- 是否允许子包,默认为false -->
<property name="enableSubPackages" value="false"/>
<!-- 是否针对string类型的字段在set方法中进行修剪,默认false -->
<property name="trimStrings" value="true"/>
<!-- 建立modal对象是否不可改变 即生成的modal对象不会有setter方法,只有构造方法 -->
<property name="immutable" value="false"/>
<!-- 是否对modal添加构造函数 -->
<property name="constructorBased" value="true"/>
</javaModelGenerator>

<!-- 生成Mapper.xml文件 -->
<sqlMapGenerator targetPackage="mapper" targetProject="src/main/resources">
<!--<property name="enableSubPackages" value="false"/>-->
</sqlMapGenerator>

<!-- 生成 XxxMapper.java 接口-->
<javaClientGenerator targetPackage="com.hui.javalearn.dao" targetProject="src/main/java" type="XMLMAPPER">
<!--<property name="enableSubPackages" value="false"/>-->
</javaClientGenerator>

<!--
1.table可以有多个,
2.每个数据库中的表都可以写一个table
3.tableName可以使用%通配符来匹配所有数据库表,也可以指定具体的表明
4.只有匹配的表才会自动生成文件
-->
<!--
schema为数据库名,oracle需要配置,mysql不需要配置。
tableName为对应的数据库表名
domainObjectName 是要生成的实体类名(可以不指定,默认按帕斯卡命名法将表名转换成类名)
enableXXXByExample 默认为 true, 为 true 会生成一个对应Example帮助类,帮助你进行条件查询,不想要可以设为false
-->
<!--使用%通配符来匹配-->
<table tableName="%" enableCountByExample="true" enableUpdateByExample="true" enableDeleteByExample="true"
enableSelectByExample="true" selectByExampleQueryId="true">
<!-- 如果设置为true,生成的model类会直接使用column本身的名字,而不会再使用驼峰命名方法,比如create_time,生成的属性名字就是create_time,而不会是createTime -->
<property name="useActualColumnNames" value="false"/>
<!-- 数据库表主键 -->
<generatedKey column="id" sqlStatement="Mysql" identity="true"/>
<!-- 去掉表前缀-->
<!-- 这里虽然能去掉表前缀,但是针对:micro_user_information 去除后生成 UserinformationModel-->
<!-- <domainObjectRenamingRule searchString="^Micro" replaceString=""/>-->
</table>
</context>
</generatorConfiguration>

3.2 外入配置文件

<properties resource="mybatis-generator/generatorjdbc.properties"/>

**配置文件在: ** /src/main/resources/mybatis-generator/generatorjdbc.properties

**配置详情: **

# 数据库连接
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/micro_serve?characterEncoding=UTF-8&useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=root

踩坑点: 本来是打算复用application.yaml,但是一直会报错: generate failed: Exception getting JDBC Driver,看网上很多教程都是基于application.properties,无奈只能单独写一个文件(generatorjdbc.properties)引入。

4. 运行效果

image-20200908234513397

问题: 如上图所示生成,虽然去除表前缀但是生成的文件大小写还是有问题,比如:micro_user_information 去除后生成 UserinformationModel ,解决方法,以及同步到 [3.1 MyBatis Generator 生成器配置](#3.1 MyBatis Generator 生成器配置)

5.优化生成器

生成器代码是很方便,但是我想做些定制化修改,比如:

  • dao目录下面的类后缀都是Dao、model目录下面的类后缀都是Model,
  • 生成的使用示例代码,想单独放在另外一个目录中,而不是和dao的其他文件混着放。
  • 注释很多无用的英文,能不能优化
  • model(实体类)中,支持注解lombok注解等等。

像上面这些需求,以前的大佬早就有成熟的轮子,这里只需要会使用就行;我采用的是itfsw/mybatis-generator-plugin

5.1 插件中添加依赖

<build>
<plugins>
...
<!-- ++++++++++++++++++++ mybatis代码生成器插件-开始部分 ++++++++++++++++++++ -->
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.7</version>
<configuration>
<!-- mybatis的代码生成器的配置文件 -->
<configurationFile>src/main/resources/mybatis-generator/config.xml</configurationFile>
<!--允许覆盖生成的文件-->
<overwrite>true</overwrite>
<!--verbose:true是为了运行mvn mybatis-generator:generate -e时显示具体过程。-->
<verbose>true</verbose>
</configuration>
<dependencies>
<!-- mysql的JDBC驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
<!-- 优化生成器插件-->
<dependency>
<groupId>com.itfsw</groupId>
<artifactId>mybatis-generator-plugin</artifactId>
<version>1.3.8</version>
</dependency>
</dependencies>
</plugin>
<!-- ++++++++++++++++++++ mybatis代码生成器插件-结束部分 ++++++++++++++++++++ -->
</plugins>
</build>

注意点:

  • mybatis代码生成器版本不能太高,不然无法正常使用itfsw.plugin

5.2 优化配置

修改生成器配置src/main/resources/mybatis-generator/config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!--mybatis的代码生成器相关配置-->
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

<generatorConfiguration>
<!-- 引入配置文件 -->
<!-- 配置文件在: /src/main/resources/mybatis-generator/generatorjdbc.properties -->
<properties resource="mybatis-generator/generatorjdbc.properties"/>
<!--
1.一个数据库一个context
2.context的子元素必须按照它给出的顺序:
property*,plugin*,commentGenerator?,jdbcConnection,javaTypeResolver?,
javaModelGenerator,sqlMapGenerator?,javaClientGenerator?,table+
-->
<!--
id : 随便填,保证多个 context id 不重复就行
defaultModelType : 可以不填,默认值 conditional,flat表示一张表对应一个po
targetRuntime:可以不填,默认值 MyBatis3,常用的还有 MyBatis3Simple,这个配置会影响生成的 dao 和 mapper.xml的内容
-->
<context id="myContext" targetRuntime="MyBatis3" defaultModelType="flat">

<!-- 自动识别数据库关键字,默认false,如果设置为true,根据SqlReservedWords中定义的关键字列表;
一般保留默认值,遇到数据库关键字(Java关键字),使用columnOverride覆盖 -->
<property name="autoDelimitKeywords" value="true"/>

<!-- 生成的Java文件的编码 -->
<property name="javaFileEncoding" value="utf-8"/>

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

<!-- 格式化java代码 -->
<property name="javaFormatter" value="org.mybatis.generator.api.dom.DefaultJavaFormatter"/>
<!-- 格式化XML代码 -->
<property name="xmlFormatter" value="org.mybatis.generator.api.dom.DefaultXmlFormatter"/>

<!-- *************************************** 插件开始部分 ****************************************************-->
<!-- JavaBean 实现 序列化 接口 -->
<plugin type="org.mybatis.generator.plugins.SerializablePlugin"/>
<!-- generator 时,为类生成toString -->
<plugin type="org.mybatis.generator.plugins.ToStringPlugin"/>

<!-- 提供clientSuffix、exampleSuffix、modelSuffix来修改对应生成的类和文件的结尾 -->
<plugin type="com.itfsw.mybatis.generator.plugins.TableRenameConfigurationPlugin">
<!-- TbMapper -> TbDao, TbMapper.xml -> TbDao.xml -->
<property name="clientSuffix" value="Dao"/>
<!-- 发现如果使用这个修改example后缀后,指定example类目录的插件就会失效-->
<!-- <property name="exampleSuffix" value="Query"/>-->
<!-- 实体类添加后缀-->
<property name="modelSuffix" value="Model"/>
</plugin>

<!-- Table重命名插件 -->
<!-- 去掉表前缀,解决:micro_user_information 去除后生成 UserinformationModel问题-->
<plugin type="com.itfsw.mybatis.generator.plugins.TableRenamePlugin">
<!-- 可根据具体需求确定是否配置 -->
<property name="searchString" value="^Micro"/>
<property name="replaceString" value=""/>
</plugin>
<!-- Example Criteria 增强插件 -->
<plugin type="com.itfsw.mybatis.generator.plugins.ExampleTargetPlugin">
<!-- 修改Example类生成到目标包下 -->
<property name="targetPackage" value="com.hui.javalearn.dao.example"/>
</plugin>

<!-- 自定义注释插件 -->
<plugin type="com.itfsw.mybatis.generator.plugins.CommentPlugin">
<!-- 自定义模板路径 -->
<property name="template" value="${mybatis.comment.file}"/>
</plugin>
<!-- Lombok插件 去除模型中的get和set ,用@Data注解取代 -->
<plugin type="com.itfsw.mybatis.generator.plugins.LombokPlugin">
<!-- @Data 默认开启,同时插件会对子类自动附加@EqualsAndHashCode(callSuper = true),@ToString(callSuper = true) -->
<property name="@Data" value="true"/>
<!-- @Builder 必须在 Lombok 版本 >= 1.18.2 的情况下开启,对存在继承关系的类自动替换成@SuperBuilder -->
<property name="@Builder" value="false"/>
<!-- @NoArgsConstructor 和 @AllArgsConstructor 使用规则和Lombok一致 -->
<property name="@AllArgsConstructor" value="false"/>
<property name="@NoArgsConstructor" value="false"/>
<!-- @Getter、@Setter、@Accessors 等使用规则参见官方文档 -->
<property name="@Accessors(chain = true)" value="false"/>
<!-- 临时解决IDEA工具对@SuperBuilder的不支持问题,开启后(默认未开启)插件在遇到@SuperBuilder注解时会调用ModelBuilderPlugin来生成相应的builder代码 -->
<property name="supportSuperBuilderForIdea" value="false"/>
</plugin>
<!-- *************************************** 插件结束部分 ****************************************************-->


<!-- 注释 -->
<commentGenerator>
<!-- 是否取消注释 true:否 false:是 -->
<property name="suppressAllComments" value="false"/>
<!-- 是否生成注释代时间戳 -->
<property name="suppressDate" value="false"/>
<!-- 生成时间的格式-->
<property name="dateFormat" value="yyyy-MM-dd HH:mm:ss "/>
<!-- 是否带上数据库字段备注信息,只有suppressAllComments为false时才生效-->
<property name="addRemarkComments" value="true"/>
</commentGenerator>


<!-- jdbc连接 -->
<jdbcConnection driverClass="${spring.datasource.driverClassName}"
connectionURL="${spring.datasource.url}"
userId="${spring.datasource.username}"
password="${spring.datasource.password}">
<!--高版本的 mysql-connector-java 需要设置 nullCatalogMeansCurrent=true-->
<property name="nullCatalogMeansCurrent" value="true"/>
</jdbcConnection>

<!-- 类型转换 -->
<javaTypeResolver>
<!--是否使用bigDecimal,默认false。
false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer
true,把JDBC DECIMAL 和 NUMERIC 类型解析为java.math.BigDecimal-->
<property name="forceBigDecimals" value="true"/>
<!--是否使用转换日期,默认false
false,将所有 JDBC 的时间类型解析为 java.util.Date
true,将 JDBC 的时间类型按如下规则解析
DATE -> java.time.LocalDate
TIME -> java.time.LocalTime
TIMESTAMP -> java.time.LocalDateTime
TIME_WITH_TIMEZONE -> java.time.OffsetTime
TIMESTAMP_WITH_TIMEZONE -> java.time.OffsetDateTime
-->
<!--<property name="useJSR310Types" value="false"/>-->
</javaTypeResolver>

<!-- 生成实体类地址 -->
<javaModelGenerator targetPackage="com.hui.javalearn.model" targetProject="src/main/java">
<!-- 是否允许子包,默认为false -->
<property name="enableSubPackages" value="false"/>
<!-- 是否针对string类型的字段在set方法中进行修剪,默认false -->
<property name="trimStrings" value="true"/>
<!-- 建立modal对象是否不可改变 即生成的modal对象不会有setter方法,只有构造方法 -->
<property name="immutable" value="false"/>
<!-- 是否对modal添加构造函数 -->
<property name="constructorBased" value="true"/>
</javaModelGenerator>

<!-- 生成Mapper.xml文件 -->
<sqlMapGenerator targetPackage="mapper" targetProject="src/main/resources">
<!--<property name="enableSubPackages" value="false"/>-->
</sqlMapGenerator>

<!-- 生成 XxxMapper.java 接口-->
<javaClientGenerator targetPackage="com.hui.javalearn.dao" targetProject="src/main/java" type="XMLMAPPER">
<!--<property name="enableSubPackages" value="false"/>-->
</javaClientGenerator>

<!--
1.table可以有多个,
2.每个数据库中的表都可以写一个table
3.tableName可以使用%通配符来匹配所有数据库表,也可以指定具体的表明
4.只有匹配的表才会自动生成文件
-->
<!--
schema为数据库名,oracle需要配置,mysql不需要配置。
tableName为对应的数据库表名
domainObjectName 是要生成的实体类名(可以不指定,默认按帕斯卡命名法将表名转换成类名)
enableXXXByExample 默认为 true, 为 true 会生成一个对应Example帮助类,帮助你进行条件查询,不想要可以设为false
-->
<!--使用%通配符来匹配-->
<!-- <table tableName="%" enableCountByExample="true" enableUpdateByExample="true" enableDeleteByExample="true"-->
<!-- enableSelectByExample="true" selectByExampleQueryId="true">-->
<!-- &lt;!&ndash; 如果设置为true,生成的model类会直接使用column本身的名字,而不会再使用驼峰命名方法,比如create_time,生成的属性名字就是create_time,而不会是createTime &ndash;&gt;-->
<!-- <property name="useActualColumnNames" value="false"/>-->
<!-- &lt;!&ndash; 数据库表主键 &ndash;&gt;-->
<!-- <generatedKey column="id" sqlStatement="Mysql" identity="true"/>-->
<!-- &lt;!&ndash; 去掉表前缀&ndash;&gt;-->
<!-- &lt;!&ndash; 这里虽然能去掉表前缀,但是针对:micro_user_information 去除后生成 UserinformationModel&ndash;&gt;-->
<!--&lt;!&ndash; <domainObjectRenamingRule searchString="^Micro" replaceString=""/>&ndash;&gt;-->
<!-- </table>-->

<!--使用具体表生成-->
<table tableName="micro_student_subject" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false"
enableSelectByExample="false" selectByExampleQueryId="true">
<!-- 如果设置为true,生成的model类会直接使用column本身的名字,而不会再使用驼峰命名方法,比如create_time,生成的属性名字就是create_time,而不会是createTime -->
<property name="useActualColumnNames" value="false"/>
<!-- 数据库表主键 -->
<generatedKey column="id" sqlStatement="Mysql" identity="true"/>
</table>
</context>
</generatorConfiguration>

5.3 自定义注释

  • 需要修改外入配置文件 /src/main/resources/mybatis-generator/generatorjdbc.properties
# 数据库连接
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/micro_serve?characterEncoding=UTF-8&useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=root

# 自定义注释文件位置
mybatis.comment.file=src/main/resources/mybatis-generator/mybatis-generator-comment.ftl
  • 在生成器配置中引入配置文件 src/main/resources/mybatis-generator/config.xml

     <!-- 自定义注释插件 -->
    <plugin type="com.itfsw.mybatis.generator.plugins.CommentPlugin">
    <!-- 自定义模板路径 -->
    <property name="template" value="${mybatis.comment.file}"/>
    </plugin>
  • 定义注释模板 src/main/resources/mybatis-generator/mybatis-generator-comment.ftl

    具体代码

    <?xml version="1.0" encoding="UTF-8"?>
    <template>
    <!-- #############################################################################################################
    /**
    * This method is called to add a file level comment to a generated java file. This method could be used to add a
    * general file comment (such as a copyright notice). However, note that the Java file merge function in Eclipse
    * does not deal with this comment. If you run the generator repeatedly, you will only retain the comment from the
    * initial run.
    *
    * The default implementation does nothing.
    *
    * @param compilationUnit
    * the compilation unit
    */
    -->
    <comment ID="addJavaFileComment"><![CDATA[
    /**
    * @author : Mr.Liuqh
    * @date : ${.now?string["yyyy-MM-dd HH:mm:ss"]}
    */
    ]]>
    </comment>

    <!-- #############################################################################################################
    /**
    * This method should add a suitable comment as a child element of the specified xmlElement to warn users that the
    * element was generated and is subject to regeneration.
    *
    * @param xmlElement
    * the xml element
    */
    -->
    <comment ID="addComment"><![CDATA[
    <!--
    WARNING - ${mgb}
    This element is automatically generated by MyBatis Generator, do not modify.
    @project https://github.com/itfsw/mybatis-generator-plugin
    -->
    ]]>
    </comment>

    <!-- #############################################################################################################
    /**
    * This method is called to add a comment as the first child of the root element. This method could be used to add a
    * general file comment (such as a copyright notice). However, note that the XML file merge function does not deal
    * with this comment. If you run the generator repeatedly, you will only retain the comment from the initial run.
    *
    * The default implementation does nothing.
    *
    * @param rootElement
    * the root element
    */
    -->
    <comment ID="addRootComment"></comment>

    <!-- #############################################################################################################
    /**
    * This method should add a Javadoc comment to the specified field. The field is related to the specified table and
    * is used to hold the value of the specified column.
    *
    * <b>Important:</b> This method should add a the nonstandard JavaDoc tag "@mbg.generated" to the comment. Without
    * this tag, the Eclipse based Java merge feature will fail.
    *
    * @param field
    * the field
    * @param introspectedTable
    * the introspected table
    * @param introspectedColumn
    * the introspected column
    */
    -->
    <comment ID="addFieldComment"><![CDATA[
    <#if introspectedColumn??>
    /**
    *
    <#if introspectedColumn.remarks?? && introspectedColumn.remarks != ''>
    <#list introspectedColumn.remarks?split("\n") as remark>
    * 备注:${remark}</#list>
    </#if>
    *
    * 表字段:: ${introspectedTable.fullyQualifiedTable}.${introspectedColumn.actualColumnName}
    */
    <#else>
    </#if>
    ]]>
    </comment>

    <!-- #############################################################################################################
    /**
    * Adds a comment for a model class. The Java code merger should
    * be notified not to delete the entire class in case any manual
    * changes have been made. So this method will always use the
    * "do not delete" annotation.
    *
    * Because of difficulties with the Java file merger, the default implementation
    * of this method should NOT add comments. Comments should only be added if
    * specifically requested by the user (for example, by enabling table remark comments).
    *
    * @param topLevelClass
    * the top level class
    * @param introspectedTable
    * the introspected table
    */
    -->
    <comment ID="addModelClassComment"><![CDATA[
    /***
    <#if introspectedTable.remarks?? && introspectedTable.remarks != ''>
    *
    <#list introspectedTable.remarks?split("\n") as remark>
    * ${remark}
    </#list>
    </#if>
    *
    * 表名: ${introspectedTable.fullyQualifiedTable}
    */
    ]]>
    </comment>

    <!-- #############################################################################################################
    /**
    * Adds the inner class comment.
    *
    * @param innerClass
    * the inner class
    * @param introspectedTable
    * the introspected table
    * @param markAsDoNotDelete
    * the mark as do not delete
    */
    -->
    <comment ID="addClassComment"><![CDATA[
    /****
    *
    * ${introspectedTable.fullyQualifiedTable}
    *
    * ${mgb}<#if markAsDoNotDelete?? && markAsDoNotDelete> do_not_delete_during_merge</#if>
    */
    ]]>
    </comment>

    <!-- #############################################################################################################
    /**
    * Adds the enum comment.
    *
    * @param innerEnum
    * the inner enum
    * @param introspectedTable
    * the introspected table
    */
    -->
    <comment ID="addEnumComment"><![CDATA[
    /***
    *
    * ${introspectedTable.fullyQualifiedTable}
    *
    */
    ]]>
    </comment>

    <!-- #############################################################################################################
    /**
    * Adds the interface comment.
    *
    * @param innerInterface
    * the inner interface
    * @param introspectedTable
    * the introspected table
    */
    -->
    <comment ID="addInterfaceComment"><![CDATA[
    /***
    *
    * ${introspectedTable.fullyQualifiedTable}
    */
    ]]>
    </comment>

    <!-- #############################################################################################################
    /**
    * Adds the getter comment.
    *
    * @param method
    * the method
    * @param introspectedTable
    * the introspected table
    * @param introspectedColumn
    * the introspected column
    */
    -->
    <comment ID="addGetterComment"><![CDATA[
    <#if introspectedColumn??>
    /**
    * 表字段: ${introspectedTable.fullyQualifiedTable}.${introspectedColumn.actualColumnName}
    *
    * @return the value of ${introspectedTable.fullyQualifiedTable}.${introspectedColumn.actualColumnName}
    */
    <#else>
    /**
    * field ${method.name?replace("get","")?replace("is", "")?uncap_first}
    *
    * @return the value of field ${method.name?replace("get","")?replace("is", "")?uncap_first}
    *
    */
    </#if>
    ]]>
    </comment>

    <!-- #############################################################################################################
    /**
    * Adds the setter comment.
    *
    * @param method
    * the method
    * @param introspectedTable
    * the introspected table
    * @param introspectedColumn
    * the introspected column
    */
    -->
    <comment ID="addSetterComment"><![CDATA[
    <#if introspectedColumn??>
    /**
    * 表字段: ${introspectedTable.fullyQualifiedTable}.${introspectedColumn.actualColumnName}
    *
    * @param ${method.parameters[0].name} the value for ${introspectedTable.fullyQualifiedTable}.${introspectedColumn.actualColumnName}
    */
    <#else>
    /**
    *
    * field ${method.name?replace("set","")?uncap_first}
    *
    * @param ${method.parameters[0].name} the value for field ${method.name?replace("set","")?uncap_first}
    *
    */
    </#if>
    ]]>
    </comment>

    <!-- #############################################################################################################
    /**
    * Adds the general method comment.
    *
    * @param method
    * the method
    * @param introspectedTable
    * the introspected table
    */
    -->
    <comment ID="addGeneralMethodComment">

    </comment>
    </template>

5.4 优化后生成效果

image-20200909001944770

6.完整配置

6.1 pom.xml

<?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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.hui</groupId>
<artifactId>java-learn</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>java-learn</name>
<description>SpringBoot框架学习</description>
<!-- 变量信息-->
<properties>
<java.version>1.8</java.version>
<swagger.bootstrap.ui.version>1.9.6</swagger.bootstrap.ui.version>
<!--mybatis版本-->
<mybatis.version>2.1.2</mybatis.version>
<!--mybatis代码生成器版本-->
<!-- 坑点:这里的mybatis.generator.version版本不能太高,不然无法正常使用itfsw.plugin-->
<mybatis.generator.version>1.3.7</mybatis.generator.version>
<mysql.connector.version>8.0.21</mysql.connector.version>

</properties>

<dependencies>
<!-- web依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!--SwaggerBootstrapUi依赖 开始部分 -->
<!--文档: https://www.bookstack.cn/read/swagger-bootstrap-ui/3.md -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>swagger-bootstrap-ui</artifactId>
<version>${swagger.bootstrap.ui.version}</version>
</dependency>
<!--SwaggerBootstrapUi依赖 结束部分 -->

<!--Mybatis 开始部分 -->
<!-- Mybatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.version}</version>
</dependency>
<!-- MySql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.connector.version}</version>
<scope>runtime</scope>
</dependency>
<!--Mybatis 结束部分 -->

<!--lombok 开始部分 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--lombok 结束部分 -->

<!-- 单元测试-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>

<!--解决报错: Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.22.2:test-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
<!-- ++++++++++++++++++++ mybatis代码生成器插件-开始部分 ++++++++++++++++++++ -->
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>${mybatis.generator.version}</version>
<configuration>
<!-- mybatis的代码生成器的配置文件 -->
<configurationFile>src/main/resources/mybatis-generator/config.xml</configurationFile>
<!--允许覆盖生成的文件-->
<overwrite>true</overwrite>
<!--verbose:true是为了运行mvn mybatis-generator:generate -e时显示具体过程。-->
<verbose>true</verbose>
</configuration>
<dependencies>
<!-- mysql的JDBC驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.connector.version}</version>
</dependency>
<!-- https://github.com/itfsw/mybatis-generator-plugin-->
<dependency>
<groupId>com.itfsw</groupId>
<artifactId>mybatis-generator-plugin</artifactId>
<version>1.3.8</version>
</dependency>
</dependencies>
</plugin>
<!-- ++++++++++++++++++++ mybatis代码生成器插件-结束部分 ++++++++++++++++++++ -->
</plugins>
</build>
</project>

7. 踩坑记录

7.1 操作Dao方法时报错: Invalid bound statement (not found)

# 报错内容
2020-09-14 23:01:32.394 ERROR 67618 --- [nio-8080-exec-6] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.hui.javalearn.dao.UserDao.insert] with root cause

解决方法:

修改application.yaml关于mybatis配置,如下

server:
port: 8080
spring:
# 数据库相关的配置
datasource:
url: jdbc:mysql://127.0.0.1:3306/micro_serve?characterEncoding=UTF-8&useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai
username: root
password: liuqh112233
driver-class-name: com.mysql.cj.jdbc.Driver
# mybatis相关的配置
mybatis:
# 实体类
type-aliases-package: com.hui.javalearn.model
# (添加这行配置)mapper xml文件地址;注意:classpath* 指的是扫描所有模块的资源路径
mapper-locations: classpath*:mapper/*.xml

7.2 报错: …bean of type ‘com.hui.javalearn.dao.UserDao’ that could not be found

在一个新的工程中,用MyBatis Gennrator自动生成DAO,Example,Mapper以及对应的XML后,然后使用自动装载的方式加载Mapper,在执行时报错。

...
Description:

Field userService in com.hui.javalearn.controller.UserController required a bean of type 'com.hui.javalearn.dao.UserDao' that could not be found.

The injection point has the following annotations:
- @org.springframework.beans.factory.annotation.Autowired(required=true)


Action:

Consider defining a bean of type 'com.hui.javalearn.dao.UserDao' in your configuration.
...

解决方法: 在启动类中添加Mapper扫描路径,具体如下

package com.hui.javalearn;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
// 添加扫描路径
@MapperScan("com.hui.javalearn.dao")
public class JavaLearnApplication {
public static void main(String[] args) {
SpringApplication.run(JavaLearnApplication.class, args);
}
}