MyBatis-Generator 是 MyBatis 提供的一个代码生成工具,可以帮助我们生成数据库表对应的持久化对象(也称作 Model、PO)、操作数据库的接口(dao)、简单 SQL 的 mapper(XML 形式或注解形式)。
MyBatis-Generator (常简写为 MBG 或 mbg)是一个独立工具,你可以下载它的 jar 包来运行,也可以在 Ant 和 Maven 中运行。其官方网址为: mybatis.org/generator/
对于这篇博文,我是在基于 SpringBoot 的 Maven 项目 环境中配置、使用和讲解的,使用的 IDE 是 IntelliJ IDEA。
既然需要使用 MyBatis-Generator,那么在项目中就一定使用了 MyBatis 和某一种数据库,并且这些依赖应该已经在 Maven 中配置好了。例如 pom 文件中的配置:
<dependencies>
<!-- 为了方便,不展示其它配置... -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
</dependencies>
复制代码
对于在 Maven 项目中引入 MyBatis-Generator,这里介绍 两种方式 ,具体需要用哪种方式取决于你使用哪种方式来运行 MyBatis-Generator 工具:(对于如何运行 MyBatis-Generator 工具,参见本文第三节)
这种方式适用于:用 Java 代码来运行 MyBatis-Generator 工具。在 pom 文件中引入 mybatis-generator-core 依赖:
<dependencies>
<!-- 为了方便,不展示其它配置... -->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.7</version>
</dependency>
</dependencies>
复制代码
这种方式适用于:通过 Maven 项目的 Plugins 或 Maven 的命令行来运行 MyBatis-Generator 工具。在 pom 文件中引入 mybatis-generator-maven-plugin 插件:
<build>
<!-- 为了方便,不展示其它配置... -->
<plugins>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.7</version>
</plugin>
</plugins>
</build>
复制代码
MyBatis-Generator 需要一个 xml 配置文件,来详细配置生成代码的各种细节。例如,在 项目的 resources 目录下 新建一个 mybatis-generator-config.xml 配置文件:
其内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<!-- MyBatis-Generator 相关配置 -->
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<!-- 所有的配置均在根元素 generatorConfiguration 下 -->
<generatorConfiguration>
...
...
</generatorConfiguration>
复制代码
在该文件中,所有的配置均在根元素 generatorConfiguration 下。根元素 generatorConfiguration 有 3 个子元素可供配置,这 3 个子元素必须按照下面给出的 次数和顺序 进行配置:( 没错,MyBatis-Generator 对配置的顺序也有严格的要求 )
其中,properties 和 classPathEntry 元素用于引入外部配置或文件;context 是核心元素,里面包含有各种详细配置。
在配置 MyBatis-Generator 时,是可以引入外部配置或文件的。
元素 properties 可以用于加载外部配置项或配置文件,该元素有两个属性,均用来指定外部配置文件的地址:
file:///Users/deecyn/Files/mybatis-generator.properties
注意,这两个属性 只能选择一个 使用。例如,引入下图中的 mybatis-generator.properties 配置文件:
用于引入文件的代码如下:
<!-- 引入外部配置文件 --> <properties resource="mybatis-generator.properties"/> 复制代码
之后在整个 xml 配置文件中就可以通过 ${propertyKey} 的方式来引用配置项。
使用 classPathEntry 元素,可以在 MBG 工作的时候,加载额外需要的依赖包。其中,location 属性指明需要加载的 jar/zip 包的全路径。例如:
<!-- 加载需要的额外的依赖包 --> <classPathEntry location="/Users/deecyn/Files/db2java.zip"/> 复制代码
在 generationConfiguration 的子元素中,context 是核心元素,用于配置生成一组对象的环境。元素 context 有 4 个属性可供配置:
示例配置如下:
<context id="MySqlContext" targetRuntime="MyBatis3" defaultModelType="flat"> ... </context> 复制代码
元素 context 中,有多个子元素需要配置。同样的,context 的子元素必须按照下面给出的 次数和顺序 进行配置:
可以看出,javaModelGenerator、table 以及 connection 元素的配置是必需的。
用于为代码生成指定属性,或为其它元素指定属性。可以配置零个或多个,常见的 property 配置如下:
<!-- 自动识别数据库关键字,默认为 false,一般保留默认值,遇到数据库关键字(Java关键字)时,按照 table 元素中 columnOverride 属性的配置进行覆盖;
如果设置为 true, 则需按照 SqlReservedWords 中定义的关键字列表,对关键字进行定界(分隔);
定界符(分隔符)参见 beginningDelimiter 和 endingDelimiter 的设置-->
<property name="autoDelimitKeywords" value="false"/>
<!-- beginningDelimiter 和 endingDelimiter,定界符(分隔符),指明用于标记数据库关键字的符号,默认为为双引号 (");
在 oracle 中是双引号 ("),在 MySQL 中需配置为反引号 (`) -->
<property name="beginningDelimiter" value="`"/>
<property name="endingDelimiter" value="`"/>
<!-- 生成的 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"/>
复制代码
注: SqlReservedWords 关键字列表
配置插件,可以有零个或多个,常见的 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"/> 复制代码
可以配置 0 个或 1 个,用来配置生成的注释,默认是生成注释的,并且会在注释中添加时间等信息。如果想沿用默认的注释配置的话,可以不用配置 commentGenerator 元素。否则,可以进行如下配置:
<commentGenerator> <!-- 不生成所有注释,默认为 false --> <property name="suppressAllComments" value="true"/> <!-- 生成的注释中不包含时间信息,默认为 false --> <property name="suppressDate" value="true"/> <!-- 生成的注释中,时间的显示格式 --> <property name="dateFormat" value="yyyy/MM/dd"/> <!-- 是否添加数据库表中字段的注释,默认为 false --> <property name="addRemarkComments" value="true"/> </commentGenerator> 复制代码
当然,你也可以 自定注释生成器 。
配置数据库连接,具体如下:
<!-- 配置数据库连接 -->
<jdbcConnection driverClass="${jdbc.driverClass}"
connectionURL="${jdbc.connectionURL}"
userId="${jdbc.userId}"
password="${jdbc.password}">
<!-- 若为 8.0 版本以上的 mysql-connector-java 驱动,需要设置 nullCatalogMeansCurrent = true -->
<!-- <property name="nullCatalogMeansCurrent" value="true"/> -->
</jdbcConnection>
复制代码
其中, ${propertyKey} 里面是引用的外部配置文件中的 propertyValue:
你也可以写死,那么就不用在 <properties resource=""/> 中引入此文件了。
这里面值得注意的是 <property name="nullCatalogMeansCurrent" value="true"/> ,当 mysql-connector-java 驱动在 8.0 版本以上时,如果不配置这一项为 true,会不生成指定数据库中表的 Mapper。具体原因可参考文章: MyBatis Generator踩坑与自救 。
可以配置 0 或 1 个,用来配置 JDBC 到 Java 中的类型转换规则,如果不进行配置,则使用默认的转换规则,默认使用 org.mybatis.generator.internal.types.JavaTypeResolverDefaultImpl 。
就算要配置,也只能配置 BigDecimal 和时间类型的转换:
<javaTypeResolver>
<!-- 是否强制使用 BigDecimal;
默认为 false,把 JDBC 的 DECIMAL 和 NUMERIC 类型解析为 Integer;
设置为 true 时,把 JDBC 的 DECIMAL 和 NUMERIC 类型解析为 java.math.BigDecimal
-->
<property name="forceBigDecimals" value="true"/>
<!-- 设置时间类型的转换,
默认 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="true"/>
</javaTypeResolver>
复制代码
Java 模型生成器,有且仅能配置一个,负责 key 类(见 context 元素的 defaultModelType 属性)、Java Bean 实体类、查询类的生成。
元素 javaModelGenerator 有两个属性:
在 javaModelGenerator 元素中还可以配置多个 property 子元素,具体代码如下:
<!-- 配置 Java 模型生成器 -->
<javaModelGenerator targetPackage="deecyn.shop_02.mbg.model" targetProject="src/main/java">
<!-- 自动为每一个生成的类创建一个构造方法,构造方法包含了所有的 field,而不是使用 setter;
默认值为 false -->
<property name="constructorBased" value="false"/>
<!-- 在 targetPackage 的基础上,根据数据库的 schema 再生成一层 package,
最终生成的类放在这个package下;默认为false -->
<property name="enableSubPackages" value="false"/>
<!-- 是否创建一个不可变的类:如果为true,那么 MBG 生成的类会没有 setter 方法,
采用构造函数的方式来接收和设置每个字段的值,此时会忽略 constructorBased 属性的设置;
默认值为 false -->
<property name="immutable" value="false"/>
<!-- 设置在 getter 方法中,是否对 String 类型的字段调用 trim() 方法;默认为 false -->
<property name="trimStrings" value="true"/>
</javaModelGenerator>
复制代码
可以配置 0 或 1 个,生成 SQL Map 的 xml 文件生成器。在 MyBatis3 之后,我们可以使用 mapper.xml 文件 + Mapper 接口,或者只使用 Mapper 接口 + Annotation;所以,如果 javaClientGenerator 元素中配置了需要生成 xml 的话,这个元素就必须配置。
该元素有 targetPackage 和 targetProject 两个属性,原理与 javaModelGenerator 元素的相同,只不过这里指的是 resource 目录下存放 mapper.xml 文件的路径。具体代码如下:
<!-- SQL Map 的 xml 文件生成器 --> <sqlMapGenerator targetPackage="mbg-mapper" targetProject="src/main/resources"> <!-- 同 javaModelGenerator 元素中的配置 --> <property name="enableSubPackages" value="false"/> </sqlMapGenerator> 复制代码
可以配置 0 或 1 个,用于配置关于 Mapper 接口的生成,如果没有配置该元素,那么默认不会生成 Mapper 接口。
元素 javaClientGenerator 有 3 个属性,其中 targetPackage 和 targetProject 属性的配置与 javaModelGenerator 元素的原理相同,只不过这里指的是 java 目录下存放 Mapper 接口的路径。关于 type 属性,有 3 个可选值:
注意,如果 context 元素的 defaultModelType 属性设置为 MyBatis3Simple,那么就只支持 ANNOTATEDMAPPER 和 XMLMAPPER 的方式。 一般建议将 type 设置成 XMLMAPPER 。
<!-- 关于 Mapper 接口的生成 -->
<javaClientGenerator type="XMLMAPPER" targetPackage="deecyn.shop_02.mbg.mapper"
targetProject="src/main/java">
<!-- 同 javaModelGenerator 元素中的配置 -->
<property name="enableSubPackages" value="false"/>
</javaClientGenerator>
复制代码
一个 table 元素对应一张数据库表,如果想同时为多张表生成代码,需要配置多个 table 元素;或者可以将 tableName 设置为 % 来为全部表生成代码。
元素 table 除开一个必须的属性 tableName (数据库表名称)需要设置外,还有很多 可选 的属性,部分属性如下:
此外,table 元素中还可以配置多个 property 和 columnOverride 等子元素。示例代码如下:
<!-- 配置需要生成代码的数据库表 -->
<table tableName="pms_brand" domainObjectName="PmsBrand"
enableCountByExample="false" enableUpdateByExample="false"
enableDeleteByExample="false" enableSelectByExample="false"
selectByExampleQueryId="false">
<!-- 指定是否只生成 domain 类,默认为 false;
如果设置为 true,则只生成 domain 类,如果还配置了sqlMapGenerator,那么
在 mapper.xml 文件中,只生成 resultMap 元素 -->
<property name="modelOnly" value="false"/>
<!-- 默认为 false;如果设置为 true,生成的 model 类会直接使用 column 本身的名字,而不会再使用驼峰命名方法。比如 CREATE_DATE,生成的属性名字就是 CREATE_DATE,而不会是 createDate -->
<property name="useActualColumnNames" value="false"/>
<!-- 生成主键的方法,如果设置了该元素,MBG 会在生成的 <insert> 元素中生成一条正确的 <selectKey> 元素 -->
<generatedKey column="id" sqlStatement="MySql" identity="true"/>
<!-- 用来修改表中某个列的属性,MBG 会根据修改后的配置来生成 domain 的属性;
column:要重新设置的列名;一个 table 元素中可以定义多个 columnOverride 元素哈 -->
<columnOverride column="show_status">
<!-- 使用 property 属性来指定列要生成的属性名称 -->
<property name="property" value="showStatus"/>
<!-- javaType 用于指定生成的 domain 的属性类型,使用类型的全限定名-->
<property name="javaType" value="java.lang.Integer"/>
<!-- jdbcType用于指定该列的JDBC类型
<property name="jdbcType" value=""/>
-->
</columnOverride>
</table>
复制代码
对于 MyBatis-Generator,不同的运行方式,对项目和文件的配置会有一些区别,本文介绍两种运行 MBG 的方式。
通过这种方式运行 MBG,在本文的第一节,引入 MyBatis-Generator 时,需要按照方式一在 Maven 的 pom 文件中引入依赖:
<dependencies>
<!-- 为了方便,不展示其它配置... -->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.7</version>
</dependency>
</dependencies>
复制代码
然后在项目中新建一个 Java 类,代码类似下面:
package deecyn.shop_02.mbg;
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;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
public class Generator {
public static void main(String[] args) throws Exception {
// MBG 执行过程中的警告信息
List<String> warnings = new ArrayList<String>();
// 当生成的代码重复时,覆盖原代码
boolean overwrite = true;
// 读取我们的 MBG 配置文件
InputStream is = Generator.class.getResourceAsStream("/mybatis-generator-config.xml");
ConfigurationParser cp = new ConfigurationParser(warnings);
Configuration config = cp.parseConfiguration(is);
is.close();
DefaultShellCallback callback = new DefaultShellCallback(overwrite);
//创建 MBG
MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
//执行生成代码
myBatisGenerator.generate(null);
//输出警告信息
for (String warning : warnings) {
System.out.println(warning);
}
}
}
复制代码
运行类中的 main() 方法即可在相应的目录下生成对应的代码。
需要注意的是,当你的项目中有多个 Module 时,在配置 javaModelGenerator、sqlMapGenerator 和 javaClientGenerator 元素的 targetProject 属性时,需要在前面加上当前的 Module 名称。例如当前的 Module 名称为 shop_02 时:
<javaModelGenerator targetPackage="deecyn.shop_02.mbg.model" targetProject="shop_02/src/main/java"/>
<sqlMapGenerator targetPackage="mbg-mapper" targetProject="shop_02/src/main/resources"/>
<javaClientGenerator type="XMLMAPPER" targetPackage="deecyn.shop_02.mbg.mapper"
targetProject="shop_02/src/main/java"/>
复制代码
否则会提示找不到对应的 java 和 resource 目录。
通过这种方式运行 MBG,在本文的第一节,引入 MyBatis-Generator 时,需要按照方式二在 Maven 的 pom 文件中引入插件,此外还需要进行一些配置:
<build>
<!-- 为了方便,不展示其它配置... -->
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.7</version>
<configuration>
<!-- 引入 MyBatis-Generator 的配置文件 -->
<configurationFile>./src/main/resources/generatorConfig.xml</configurationFile>
<!-- 允许 MBG 将构建消息写入日志中 -->
<verbose>true</verbose>
<!-- 再次运行 MBG 时,允许覆盖已生成的文件,但是不会覆盖 xml 文件 -->
<overwrite>true</overwrite>
</configuration>
<dependencies>
<!-- 引入 mysql 的 JDBC 驱动,否则会报错找不到驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.48</version>
</dependency>
</dependencies>
</plugin>
</build>
复制代码
配置好后,双击 Maven --> Plugins 中的 MyBatis-Generator 运行:
即可在相应的目录下生成对应的代码。
需要注意的是,此时,在配置 javaModelGenerator、sqlMapGenerator 和 javaClientGenerator 元素的 targetProject 属性时,其路径都是相对于当前 Project 或 Module 的,不需要加前缀。例如当前的 Module 名称为 shop_02 时:
<javaModelGenerator targetPackage="deecyn.shop_02.mbg.model" targetProject="src/main/java"/>
<sqlMapGenerator targetPackage="mbg-mapper" targetProject="src/main/resources"/>
<javaClientGenerator type="XMLMAPPER" targetPackage="deecyn.shop_02.mbg.mapper"
targetProject="src/main/java"/>
复制代码
否则会提示找不到对应的 java 和 resource 目录。