Contents

MyBatis Generator 使用与原理(上)

这两天在看一个开源的小说管理平台的代码,发现它的项目使用了MyBatis Generator来生成代码操作数据库,花了两个早上的时间研究了一下,确实是很不错的工具,能在我们的开发过程中省掉不少的工作。

mybatis generator 的使用大致分成几步:

  1. 创建配置文件
  2. 保存配置文件到本地
  3. 执行 MyBatis Generator

我们以一个例子来说明如何使用 MyBaits Generator,项目的结构如下所示:

├── pom.xml
├── README.md
├── src
│   ├── main
│   │   ├── java
│   │   │   └── com
│   │   │       └── xueqiang
│   │   │           └── footmark
│   │   │               ├── controller
│   │   │               ├── FootmarkApplication.java
│   │   │               ├── model
│   │   │               ├── service
│   │   │               └── utils
│   │   └── resources
│   │       ├── application.properties
│   │       ├── log4j.properties
│   │       ├── mybatis
│   │       │   └── generator-configuration.xml
│   └── test

1. 配置文件

resources/mybatis/ 目录下创建配置文件 generator-configuration.xml,该文件的具体内容如下所示:

<?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>
    <!-- 全局配置文件,下面可以通过占位符的形式读取文件中的值 -->
<!--    <properties resource="db.properties"/>-->
    <!-- 用来指定数据源驱动包(jar/zip)的绝对路径 -->
    <classPathEntry location="D:\Users\xueqiang.chen\.m2\repository\mysql\mysql-connector-java\8.0.11\mysql-connector-java-8.0.11.jar"/>
    <!-- 用于运行时的解析模式和具体的代码生成行为,对应org.mybatis.generator.config.Context类 -->
    <!--
    id:Context示例的唯一ID,用于输出错误信息时候作为唯一标记
    targetRuntime:用于执行代码生成模式。可选值:
        MyBatis3DynamicSql:动态SQL
        MyBatis3Kotlin:基于Kotlin生成
        MyBatis3:提供基本的基于动态SQL的CRUD方法和XXXByExample方法,会生成XML映射文件
        MyBatis3Simple:提供基本的基于动态SQL的CRUD方法,会生成XML映射文件
        MyBatis3DynamicSqlV1:已经过时,不推荐使用
    defaultModeType:控制Domain类的生成行为。执行引擎为MyBatis3DynamicSql或者MyBatis3Kotlin时忽略此配置,可选值:
        conditional:默认值,类似hierarchical,但是只有一个主键的时候会合并所有属性生成在同一个类。
        flat:所有内容全部生成在一个对象中。
        hierarchical:键生成一个XXKey对象,Blob等单独生成一个对象,其他简单属性在一个对象中
    -->
    <!--
    context的内容需要按照顺序排列,否则会报错:
    property->plugin->commentGenerator->connectionFactory|jdbcConnection->javaTypeResolver->javaModelGenerator->sqlMapGenerator->javaClientGenerator->table
    -->
    <context id="default" targetRuntime="MyBatis3DynamicSql">
        <property name="javaFileEncoding" value="UTF-8"/>

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

        <!--用于控制生成的实体的注释内容
        suppressAllComments:是否生成注释
        suppressDate:是否在注释中添加生成的时间戳
        dateFormat:配合suppressDate使用,指定输出时间戳的格式
        addRemarkComments:是否输出表和列的Comment信息-->
        <commentGenerator>
            <property name="suppressDate" value="true"/>
            <property name="suppressAllComments" value="true"/>
        </commentGenerator>

        <!--用于指定数据源的连接信息,对应的类为org.mybatis.generator.config.JDBCConnectionConfiguration
        driverClass:数据源驱动的全类名
        connectionURL:JDBC的连接URL
        userId:用户名
        password:密码-->
        <jdbcConnection driverClass="com.mysql.jdbc.Driver"
                        connectionURL="jdbc:mysql://127.0.0.1:3306/footmark"
                        userId="root"
                        password="mysql">
        </jdbcConnection>

        <!--用于解析和计算数据库列类型和Java类型的映射关系,该标签只包含一个type属性,用于指定org.mybatis.generator.api.JavaTypeResolver接口的实现类
        forceBigDecimals:是否强制把所有的数字类型强制使用java.math.BigDecimal类型表示
        useJSR310Types:是否支持JSR310,主要是JSR310的新日期类型
            数据库JDBC类型           Java类型
            DATE	                java.time.LocalDate
            TIME	                java.time.LocalTime
            TIMESTAMP	            java.time.LocalDateTime
            TIME_WITH_TIMEZONE	    java.time.OffsetTime
            TIMESTAMP_WITH_TIMEZONE	java.time.OffsetDateTime-->
        <javaTypeResolver>
            <!-- 不强制把所有的数字类型转化为BigDecimal -->
            <property name="forceBigDecimals" value="false" />
        </javaTypeResolver>

        <!--主要用于控制实体(Model)类的代码生成行为
        targetPackage:生成的实体类的包名
        targetProject:生成的实体类文件相对于项目(根目录)的位置

        property:
        constructorBased:是否生成一个带有所有字段属性的构造函数
        enableSubPackages:是否允许通过Schema生成子包
        exampleTargetPackage:生成的伴随实体类的Example类的包名
        exampleTargetProject:生成的伴随实体类的Example类文件相对于项目(根目录)的位置
        immutable:是否不可变
        rootClass:为生成的实体类添加父类
        trimStrings:Setter方法是否对字符串类型进行一次trim操作-->
        <javaModelGenerator targetPackage="com.xueqiang.footmark.model.entity" targetProject="src/main/java">
            <property name="enableSubPackages" value="true" />
            <property name="trimStrings" value="true" />
        </javaModelGenerator>

        <!--主要用于控制XML映射文件的代码生成行为
        targetPackage:生成的XML映射文件的包名
        targetProject:生成的XML映射文件相对于项目(根目录)的位置,例如:src/main/resources

        property:
        enableSubPackages:是否允许通过Schema生成子包-->
        <sqlMapGenerator targetPackage="mapper"  targetProject="src/main/resources">
            <property name="enableSubPackages" value="true" />
        </sqlMapGenerator>

        <!--主要用于控制Mapper接口的代码生成行为
        type:Mapper接口生成策略.(<context>标签的targetRuntime属性为MyBatis3DynamicSql或者MyBatis3Kotlin时此属性配置忽略)
            ANNOTATEDMAPPER:Mapper接口生成的时候依赖于注解和SqlProviders(也就是纯注解实现),不会生成XML映射文件。
            XMLMAPPER:Mapper接口生成接口方法,对应的实现代码生成在XML映射文件中(也就是纯映射文件实现)
            MIXEDMAPPER:Mapper接口生成的时候复杂的方法实现生成在XML映射文件中,而简单的实现通过注解和SqlProviders实现(也就是注解和映射文件混合实现)。
        targetPackage:生成的Mapper接口的包名
        targetProject:生成的Mapper接口文件相对于项目(根目录)的位置-->
        <!--property属性:
        enableSubPackages:是否允许通过Schema生成子包
        useLegacyBuilder:是否通过SQL Builder生成动态SQL
        rootInterface:为生成的Mapper接口添加父接口-->
        <javaClientGenerator type="ANNOTATEDMAPPER" targetPackage="com.xueqiang.footmark.model.mapper"  targetProject="src/main/java">
            <property name="enableSubPackages" value="true" />
        </javaClientGenerator>

        <!--enableInsert                动态SQL提供类SqlProvider的类名称
        enableSelectByPrimaryKey        是否允许生成selectByPrimaryKey方法
        enableSelectByExample           是否允许生成selectByExample方法
        enableUpdateByPrimaryKey        是否允许生成updateByPrimaryKey方法
        enableDeleteByPrimaryKey        是否允许生成deleteByPrimaryKey方法
        enableDeleteByExample           是否允许生成deleteByExample方法
        enableCountByExample            是否允许生成countByExample方法
        enableUpdateByExample           是否允许生成updateByExample方法
        selectByPrimaryKeyQueryId       value指定对应的主键列提供列表查询功能
        selectByExampleQueryId          value指定对应的查询ID提供列表查询功能-->
        <table tableName="t_order"
               enableCountByExample="false"
               enableDeleteByExample="false"
               enableSelectByExample="true"
               enableUpdateByExample="false"
               domainObjectName="Order"
               mapperName="OrderMapper">
            <generatedKey column="id" sqlStatement="MySql"/>
        </table>

    </context>
</generatorConfiguration>

上面的这个配置文件主要是按t_order这个数据库表的属性生成整个 xml 配置文件的元素意义我们可以参考官方文档的介绍。