生成器配置文件结构

生成器配置文件generatorConfig.xml的顶层结构如下:

  • generatorConfiguration
    • classPathEntry(JDBC驱动的绝对路径)
    • properties(properties文件路径)
    • context(生成对象的环境设置)
      • property(Context作用域参数)
      • jdbcConnection(JDBC连接)
      • connectionFactory(JDBC连接工厂)
      • commentGenerator(注释生成器)
      • javaModelGenerator(实体对象生成器)
      • javaClientGenerator(Mapper 接口或实现类生成器)
      • sqlMapGenerator(xml 生成器)
      • table(用于生成对象的表)
      • javaTypeResolver(Java 类型处理器)
      • plugin(插件)

        生成器规则详解

        context*节点

        <context>节点用于指定生成一系列对象的环境。我们可以在配置文件中配置多个节点来实现从不同数据源或采用不同生成参数生成对象。

<context>节点最重要的属性是**targetRuntime**,它直接决定该环境下生成的代码风格,常用的风格为 MyBatis3DynamicSql 和 MyBatis3Simple。

属性 描述
id 用于唯一标识指定环境。必选属性
defaultModelType 指定实体对象的类型。包括三种:
flat:一个表生成一个实体类;
conditional:和 hierarchical 差不多,区别在于如果表只有一个主键,不会单独去生成一个主键类;
hierarchical:除了生成基本类,如果表中包含主键或 BLOB 列,都会单独再生成一个主键类或BLOB类
默认为 conditional,如果 targetRuntime 为 “MyBatis3Simple”、”MyBatis3DynamicSql”或”MyBatis3Kotlin”,则该属性忽略
targetRuntime 用于指定生成代码的风格(详见6.3)。
introspectedColumnImpl 指定org.mybatis.generator.api.IntrospectedColumn实现类。该类可以看成是某一列的所有信息。

<context>节点最重要的属性是**targetRuntime**,它直接决定该环境下生成的代码风格(详见6.3)。

property节点

<property>节点支持以下参数。针对 mysql 数据库,可以将定界符修改为反单引号。如果想要使用自定义的代码格式或 XML 格式,可以配置自定义实现。

属性 描述
autoDelimitKeywords 如果数据库关键字被作为列名使用,MBG 是否需要对其进行定界。
默认为false
beginningDelimiter 指定定界符的开头,默认为”
endingDelimiter 指定定界符的结尾,默认为”
javaFileEncoding 指定处理 Java 文件使用的编码
javaFormatter 指定生成 Java 代码使用的格式化器。
如果自定义的话需要实现org.mybatis.generator.api.JavaFormatter 接口并提供无参构造,默认为org.mybatis.generator.api.dom.DefaultJavaFormatter
targetJava8 指定生成 Java 代码使用的 JDK 版本
kotlinFileEncoding 不涉及
kotlinFormatter 不涉及
xmlFormatter 指定生成 XML 文件使用的格式化器。如果自定义的话需要实现org.mybatis.generator.api.XmlFormatter 接口并提供无参构造,默认为org.mybatis.generator.api.dom.DefaultXmlFormatter

jdbcConnection节点

<jdbcConnection>节点用于指定 MBG 进行数据库交互所用的 JDBC 连接。

注意,<jdbcConnection><connectionFactory>节点只要一个就行了

属性 描述
driverClass JDBC 驱动。必选属性
connectionURL JDBC URL。必选属性
userId 用户名
password 密码

包含以下子节点
<property> (0..N):用于定义 JDBC 驱动所需的一些参数,较少用到。

connectionFactory节点

<jdbcConnection>节点用于指定和配置 MBG 进行数据库交互时获取 JDBC 连接的工厂。

注意,<jdbcConnection><connectionFactory>节点只要一个就行了

属性 描述
type 用于指定 连接工厂的类。必选属性
如果自定义的话需要实现org.mybatis.generator.api.ConnectionFactory 接口并提供无参构造,默认为org.mybatis.generator.internal.JDBCConnectionFactory

<jdbcConnection>的子节点为 (0..N),参数如下表。如果是使用默认的连接工厂,这几个参数必须按照下表的提供,但是,如果是自定义的连接工厂,需要提供什么参数由你自己决定。

属性 描述
driverClass JDBC 驱动
connectionURL JDBC URL
userId 用户名
password 密码

commentGenerator*节点

<commentGenerator>节点用于指定和配置 Java 代码或 XML 文件中使用的注释生成器。

默认的注释生成器比较鸡肋,很多人都会考虑自己实现,详见6.5

属性 描述
type 用于指定注释生成器的类。
如果自定义的话需要实现org.mybatis.generator.api.CommentGenerator接口并提供无参构造,默认为org.mybatis.generator.internal.DefaultCommentGenerator

<commentGenerator>的子节点为 (0..N),参数如下表。注意,这些参数是针对默认注释生成器的,如果是自定义的,需要提供什么参数由你自己决定。

Property Name Property Values
suppressAllComments 是否不生成任何注解。默认为false。
注意,前面提到过,MBG 通过注释中的@mbg.generated来判断某个元素是不是通过 MBG 生成,如果不生成注解的话,XML 的文件覆盖功能会受到影响。
suppressDate 是否在注释中不包含时间。默认为false。
addRemarkComments 是否在注释中包含列的注释。默认为false。
dateFormat 指定时间格式。例如:yyyy-MM-dd HH:mm:ss

javaTypeResolver节点

<javaTypeResolver> 节点用于指定和配置 Java 类型解析器。默认的解析器可能会将数据库类型 decimal 或 numberic 解析为Short、Integer、Long等 Java 类型,如果我们不希望这样解析,就需要使用到这个节点。Java 类型解析器使用默认的就行,一般不会去重写它。

属性 描述
type 用于指定Java 类型解析器的类。
如果自定义的话需要实现org.mybatis.generator.api.JavaTypeResolver并提供无参构造,默认为org.mybatis.generator.internal.types.JavaTypeResolverDefaultImpl,它会将数据库类型 decimal 或 numberic 解析为 Integer 的 Java 类型

<javaTypeResolver>的子节点为 (0..N),参数如下表。注意,这些参数是针对默认注释生成器的,如果是自定义的,需要提供什么参数由你自己决定。

Property Name Property Values
forceBigDecimals 是否强制将数据库类型 decimal 或 numberic 解析为 BigDecimal 类型。默认为false,会根据数据的小数点位数和长度来决定使用 Short、Integer、Long 或 BigDecimal。
useJSR310Types 是否不强制将数据库类型 date, time 和 timestamp 解析为 Date。默认为false,如果为true,解析规则将变成:date -> LocalDate,time -> LocalTime,timestamp -> LocalDateTime

javaModelGenerator节点

<javaModelGenerator>节点用于配置实体类生成器。实体类生成器不支持自定义。

属性 描述
targetPackage 指定存放生成类的包路径。必选属性
targetProject 指定 targetPackage 的源文件夹。必选属性。如果该文件夹不存在,将会报错

<javaModelGenerator>的子节点为 (0..N),参数如下表。用的比较多的是 rootClass 和 trimStrings。

Property Name Property Values
constructorBased 是否生成包含全部参数的构造方法。
默认为false。当为true时,除了生成指定构造,还会生成对应的 resultMap。
enableSubPackages 是否在targetPackage基础上生成子包。
默认为false。当为true时,会将表所在 schema 名作为子包名
exampleTargetPackage 指定 Example 条件类的生成路径
默认和 targetPackage 相同
exampleTargetProject 指定 exampleTargetPackage 的源文件夹
默认和 targetProject 相同
immutable 如果为 true,生成的实体类将不包含 setter 方法,但会提供包含所有参数的构造。
默认为 false
rootClass 指定实体类需要继承的父类。
trimStrings 在setter方法中是否对传入字符串进行 trim 操作
默认为 false。

javaClientGenerator节点

<javaClientGenerator>节点用于指定和配置客户端类生成器。这个节点是可选的,如果不指定,则不会生成客户端类。客户端类一般指的是 Mapper 接口及 Mapper 接口的一些辅助类,例如SqlProvider 。

下面的 type 属性仅针对 MyBatis3SimpleMyBatis3 风格生效,而且 MyBatis3Simple 风格不支持 MIXEDMAPPER

属性 描述
type 用于指定使用客户端类生成器的类。
如果自定义的话需要实现org.mybatis.generator.codegen.AbstractJavaClientGenerator并提供无参构造,MBG 为我们提供了以下几种:
1. ANNOTATEDMAPPER:包含 Mapper 接口和 SqlProvider 辅助类,全注解,不包含 XML 文件;
2. XMLMAPPER:包含 Mapper 接口和 XML 文件,不包含注解;
3. MIXEDMAPPER:包含 Mapper 接口和 XML 文件,简单的 CRUD 使用注解,高级条件查询使用 XML 文件。
targetPackage 指定存放生成类的包路径。必选属性
targetProject 指定存放生成类的包路径。必选属性

的子节点为 (0..N),参数如下表。注意,这些参数是针对默认注释生成器的,如果是自定义的,需要提供什么参数由你自己决定。

Property Name Property Values
enableSubPackages 是否在 targetPackage 基础上生成子包。
默认为 false。当为 true 时,会将表所在 schema 名作为子包名
rootInterface 指定 Mapper 接口需要实现的父接口。
useLegacyBuilder 是否使用过时的SqlBuilder来构造动态语句。
默认为 false

sqlMapGenerator节点

<sqlMapGenerator> 节点用于配置 XML 生成器,不支持自定义。

属性 描述
targetPackage 指定存放生成 XML 的包路径。必选属性
targetProject 指定存放生成 XML 的包路径。必选属性

<sqlMapGenerator>的子节点为 (0..N),参数如下表。

Property Name Property Values
enableSubPackages 是否在targetPackage基础上生成子包。
默认为false。当为true时,会将表所在 schema 名作为子包名

table*节点

<table> 节点用于指定需要用于生成对象的表以及配置某些生成规则。这个节点相比前面提到的,要更加复杂一些。<table>节点支持的属性很多,一般保持默认就可以了。

属性 描述
tableName 需要生成对象的表名。必选属性。允许使用 SQL 通配符,例如:demo_%。
schema 指定数据库 schema。允许使用 SQL 通配符。
catalog 指定数据库 catalog
alias 指定查询时字段别名前缀。
如果指定,生成的 select 语句将使用alias_actualColumnName的别名
domainObjectName 指定实体类的类名。默认情况下使用驼峰命名规则。
mapperName 指定 Mapper 接口名。默认为实体类名+Mapper。
sqlProviderName 指定 SqlProvider 接口名。默认为实体类名+SqlProvider。
enableInsert
enableSelectByPrimaryKey
enableSelectByExample
enableUpdateByPrimaryKey
enableDeleteByPrimaryKey
enableDeleteByExample
enableCountByExample
enableUpdateByExample

| 是否生成指定语句。默认为true。 | | selectByPrimaryKeyQueryId
selectByExampleQueryId | 如果指定,在select 语句中将添加 ‘value’ as QUERYID | | modelType | 指定实体对象的类型。context节点中已介绍过了 | | escapeWildcards | 当 schema 或 tableName 包含 SQL 通配符,在搜素列时是否对其进行转义 | | delimitIdentifiers | 是否在 SQL 中对表名使用定界符并且使用确定的表名大小写。默认为false。 | | delimitAllColumns | 是否在 SQL 中对所有列名都添加定界符。默认为false。 |

<table>的子节点如下:

  • (0..N)
  • (0 or 1)
  • (0 or 1)
  • (0 or 1)
  • (0..N)
  • (0..N)
  • (0..N)

这几个子节点中,常用到的是,其他的用的比较少。下面挑几个来分析下:

配置的大部分参数都是为了覆盖全局的配置,并不常用。

Property Name Property Values
constructorBased 是否生成包含全部参数的构造方法。默认为false。当为true时,除了生成指定构造,还会生成对应的 resultMap。
ignoreQualifiersAtRuntime 在生成的 SQL 中,表名前是否不添加 schema 或 catalog。默认为 false
immutable 如果为 true,生成的实体类将不包含 setter 方法,但会提供包含所有参数的构造。默认为 false。
modelOnly 是否只生成实体类。默认为 false。
rootClass 指定实体类需要继承的父类。
rootInterface 指定 Mapper 接口需要实现的父接口。
runtimeCatalog 指定 SQL 中使用的 catalog
runtimeSchema 指定 SQL 中使用的 schema
runtimeTableName 指定 SQL 中使用的 tableName
selectAllOrderByClause 指定selectAll方法中加入order by ‘value’
trimStrings 实体类的 setter 方法中是否对传入字符串进行 trim 操作。默认为 false。
useActualColumnNames 是否直接使用表名作为实体类类名。默认为false。
useColumnIndexes 是否在 resultMap 中使用索引而不使用列名进行映射
useCompoundPropertyNames 是否将“列名+列注释”作为实体类的属性名

domainObjectRenamingRule/columnRenamingRule
<domainObjectRenamingRule>节点一般用于重命名实体类类名。例如,在没有指定 domainObjectName 的情况下,demo_employee 的表将生成实体类 DemoEmloyee,但我希望去掉前面的 Demo 前缀,则可以这样处理:

  1. <table tableName="demo_%" >
  2. <!-- replaceString属性可以省略 -->
  3. <domainObjectRenamingRule searchString="^Demo" replaceString=""/>
  4. </table>

另一个子节点<columnRenamingRule>也是相同的用法。

        <table tableName="demo_%" >
            <columnRenamingRule searchString="^Employee_" replaceString="" />
        </table>

gnoreColumnsByRegex/ignoreColumn
<ignoreColumnsByRegex><ignoreColumn>节点用于告诉 MBG 生成代码时忽略某些列。使用方法如下。

    <table tableName="Foo">
      <ignoreColumnsByRegex pattern="(?i)col.*">
        <except column="col01"/>
        <except column="col13"/>
      </ignoreColumnsByRegex>
    </table>

plugin*节点

<plugin>节点用于定义和配置插件。这个节点只有一个 type 属性,用于指定使用哪个插件,并通过子节点 property 来为这个插件设置参数。

官方插件

M官方为我们提供了许多好用的插件,如下:

插件 描述
org.mybatis.generator.plugins.SerializablePlugin 用于在实体类中实现java.io.Serializable接口
org.mybatis.generator.plugins.ToStringPlugin 用于在实体类中添加 toString 方法
org.mybatis.generator.plugins.EqualsHashCodePlugin 用于在实体类中添加 equals 和 hashCode 方法。
org.mybatis.generator.plugins.UnmergeableXmlMappersPlugin 用于指定不合并 XML 文件,这时 MBG 将 采用处理 Java 文件的方式来处理 XML 文件
org.mybatis.generator.plugins.CachePlugin 用于在 xml 文件中加入cache节点
org.mybatis.generator.plugins.CaseInsensitiveLikePlugin 用于在 Example 类中生成不区分大小写的Like
org.mybatis.generator.plugins.dsql.DisableDeletePlugin 禁用 MyBatisDynamicSQLV2 风格的所有删除方法
org.mybatis.generator.plugins.dsql.DisableInsertPlugin 禁用 MyBatisDynamicSQLV2 风格的所有插入方法
org.mybatis.generator.plugins.dsql.DisableUpdatePlugin 禁用 MyBatisDynamicSQLV2 风格的所有更新方法
org.mybatis.generator.plugins.FluentBuilderMethodsPlugin 用于在实体类中添加MyDomainClass withValue(Object v)方法。通过它可以实现如下赋值方式:
new Employee().withAddress(“北京”).withDeleted(false).withName(“zzs001”);
org.mybatis.generator.plugins.MapperAnnotationPlugin 用于在 Mapper 接口中添加@Mapper接口
org.mybatis.generator.plugins.MapperConfigPlugin 用于生成 Mybatis 的主配置文件 MapperConfig
org.mybatis.generator.plugins.RenameExampleClassPlugin 用于重命名 Example 类
org.mybatis.generator.plugins.RowBoundsPlugin 用于在 Mapper 接口的 selectByExample 方法参数中加入 RowBounds 参数,用于支持分页
org.mybatis.generator.plugins.VirtualPrimaryKeyPlugin 用于指定表的主键

插件的配置方式非常简单,如下:

        <!-- 插件 -->
        <plugin type="org.mybatis.generator.plugins.EqualsHashCodePlugin">
            <property name="useEqualsHashCodeFromRoot" value="true"/>
        </plugin>
        <plugin type="org.mybatis.generator.plugins.ToStringPlugin">
            <property name="useToStringFromRoot" value="true"/>
        </plugin>

运行 Java 程序,可以看到实体类中生成类 toString 、hashCode 和 equals 方法。

自定义插件

如果自定义的话,需要实现org.mybatis.generator.api.Plugin接口,并提供无参构造,当然,这里推荐继承org.mybatis.generator.api.PluginAdapter来避免重写太多方法。下面举个例子来讲解自定义插件的使用。

例如对于menu表自动生成的实体名字是 Menu,如果想命名为 MenuDomain,而生成的 Mapper 命名为 MenuDAO。为了实现这种需求,我们可以先定义一个插件,如下:

public class RenameFilePlugin extends PluginAdapter {

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

    @Override
    public void initialized(IntrospectedTable introspectedTable) {
        // 更改实体类名称,例如:cn.zzs.mybatis.entity.Menu => cn.zzs.mybatis.entity.MenuDomain
        String oldType = introspectedTable.getBaseRecordType();
        introspectedTable.setBaseRecordType(oldType + "Domain");

        // 更改Mapper名称
        String mapperType = introspectedTable.getMyBatis3JavaMapperType();
        introspectedTable.setMyBatis3JavaMapperType(mapperType.replace("Mapper", "DAO"));
    }
}

然后将插件配置:

<plugin type="cn.zzs.mybatis.plugin.RenameFilePlugin"></plugin>

下一章中我们将使用一个自定义的插件给生成的代码添加额外的注解