使用 MyBatis 时,有三种代码的格式比较固定:
- 与数据库对应的 model 类。
- 查询数据库的 dao 接口。
- 与 dao 接口相对应的 mapper 文件。
每个 dao 里面的方法基本上都需要增删改查,数据库变化,上面的这些都需要跟着变化,改动量太大。
MyBatis 团队提供了一个很强大的代码生成器——MyBatis Generator,简称 MBG,是帮助我们“偷懒”的利器。
首先,使用 MBG 需要在 pom.xml 中添加依赖:
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.6</version>
</dependency>
xml 配置
MBG 需要一个 xml 配置,下面重点介绍一下它的配置方式。
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">
xml 配置的跟元素是 <generatorConfiguration>
,它下面还有三个子标签,分别是:
- properties
- classPathEntry
- context
配置的时候,这三个标签的顺序必须是上面这个顺序。
properties 标签
这个标签用来指定外部的属性元素,最多可以配置一个,也可以不配置。使用 resource
或 url
可以指定属性文件,例如:
<properties resource="config.properties" />
config.properties
里面的内容是:
jdbc.password=123456
jdbc.username=root
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/cloud
这样在接下来的配置中,就可以使用 ${jdbc.driver}
了。
classPathEntry 标签
这个标签可以配置多个,也可以不配置。
<classPathEntry>
最常见的用法是通过属性 location
指定驱动的路径,代码如下:
<classPathEntry location=”E:\mysql\mysql-connector-java- 5.1.29.jar” />
context 标签
这个是最重要的配置,该标签至少配置一个,可以配置多个。如果配置多个,在运行 MBG 的时候还可以指定要运行的 context。
它只有一个必选属性 id,用来唯一标识该 context,还有其他可选属性:
defaultModelType
它定义了 MBG 如何生成实体类,该属性的值有:conditional
,flat
,hierarchical
。
常用的是flat
,表示该模型只为每张表生成一个实体类,这个实体类包含表中的所有字段 。targetRuntime
该属性的值有:MyBatis3
,MyBatis3Simple
。默认值是MyBatis3
。使用MyBatis3Simple
不会生成 Example 相关的方法 。
一般情况下,context 的配置是:
<context id=”Mysql” defaultModelType=”flat” >
如果不希望生成和 Example 查询有关的内容,可以这样配置:
<context id=”Mysql” defaultModelType=”flat” targetRuntime=“MyBatis3Simple”>
其他配置是 context 的子标签,有:
- property(0个或多个)
- plugin(0个或多个)
- commentGenerator(0个或1个)
- jdbcConnection(1个)
- javaTypeResolver(0个或1个)
- javaModelGenerator(1个)
- sqlMapGenerator(0个或1个)
- javaClientGenerator(0个或1个)
- table(1个或多个)
下面逐个介绍:
property 标签
不同的数据库有不同的分隔符,比如 mysql 的分隔符是反引号,sqlserver 的分隔符是方括号。property 标签的配置有:
autoDelimitKeywords
: 自动给关键词添加分隔符beginningDelimiter
: 前置分隔符endingDelimiter
: 后置分隔符javaFileEncoding
: 设置要使用的 Java 文件的编码,GBK 或 UTF-8
mysql 数据库中 property 的配置是:
<context id="Mysql" targetRuntime="MyBatis3Simple" defaultModelType="flat">
<property name="autoDelimitKeywords" value="true"/>
<property name="beginningDelimiter" value="`"/>
<property name="endingDelimiter" value="`"/>
<property name="javaFileEncoding" value="UTF-8"/>
</context>
plugin 标签
用来定义一个插件,用于扩展或修改通过 MBG 生成的代码。不是很常用。
commentGenerator 标签
用来配置如何生成注释信息。该标签有一个可选属性 type,可以指定用户的实现类,该类需要实现 org.mybatis.generator.api.CommentGenerator
接口。type属性默认值是 DEFAULT,使用默认的实现类 org.mybatis.generator.internal.DefaultCommentGenerator
。
默认的实现类中提供了三个可选属性,通过 property 进行配置:
suppressAllComments
:阻止生成注释,默认为 false。suppressDate
:阻止生成的注释包含时间,默认为 false。addRemarkComments
:注释是否添加数据库表的备注信息,默认为 false。
一般情况下,注释里面不包含日期,以免使用版本控制的时候每次都要提交。
示例配置如下:
<commentGenerator>
<property name="suppressDate" value="true"/>
<property name="addRemarkComments" value="true"/>
</commentGenerator>
生成的注释是这样的:
/**
* Database Column Remarks:
* 用户名
*
* This field was generated by MyBatis Generator.
* This field corresponds to the database column sys_user.user_name
*
* @mbg.generated
*/
private String userName;
可以自定义注释类,示例如下:
public class MyCommentGenerator extends DefaultCommentGenerator {
private boolean suppressAllComments;
private boolean addRemarkComments;
public void addConfigurationProperties(Properties properties){
super.addConfigurationProperties(properties);
suppressAllComments = isTrue(properties
.getProperty(PropertyRegistry.COMMENT_GENERATOR_SUPPRESS_ALL_COMMENTS));
addRemarkComments = isTrue(properties
.getProperty(PropertyRegistry.COMMENT_GENERATOR_ADD_REMARK_COMMENTS));
}
public void addFieldComment(Field field,
IntrospectedTable introspectedTable,
IntrospectedColumn introspectedColumn) {
if (suppressAllComments) {
return;
}
field.addJavaDocLine("/**");
String remarks = introspectedColumn.getRemarks();
if (addRemarkComments && StringUtility.stringHasValue(remarks)) {
String[] remarkLines = remarks.split(System.getProperty("line.separator")); //$NON-NLS-1$
for (String remarkLine : remarkLines) {
field.addJavaDocLine(" * " + remarkLine); //$NON-NLS-1$
}
}
field.addJavaDocLine(" * " + introspectedColumn.getActualColumnName());
field.addJavaDocLine(" */");
}
}
在 xml 中配置 commentGenerator
的 type 属性:
<commentGenerator type="com.xiaocan.generator.MyCommentGenerator">
<property name="suppressDate" value="true"/>
<property name="addRemarkComments" value="true"/>
</commentGenerator>
生成的注释是这样的:
/**
* 用户名
* user_name
*/
private String userName;
jdbcConnection 标签
这个应该再熟悉不过了:
<jdbcConnection driverClass="${jdbc.driver}" connectionURL="jdbc:mysql://localhost:3306/db_mybatis" userId="${jdbc.username}"
password="${jdbc.password}"></jdbcConnection>
上面引用了其他配置文件的属性,还记得之前的 properties 标签吧!
javaTypeResolver 标签
该标签用来指定 JDBC 类型和 Java 类型如何转换。一般使用默认的即可,不需要配置。
javaModelGenerator 标签
该标签用来控制生成的实体类,有两个必选属性:
targetPackage
:生成实例类存放的包名。targetProject
:指定目标项目路径。
它还有子标签 property,可以配置 trimStrings
:判断是否对数据库查询结果进行 trim 操作,默认为 false。如果设置为 true 就会生成如下代码:
public void setUserPassword(String userPassword) {
this.userPassword = userPassword == null ? null : userPassword.trim();
}
示例配置如下:
<javaModelGenerator targetPackage="test.model" targetProject="src/main/java">
<property name="trimStrings" value="true"/>
</javaModelGenerator>
注意上面的 targetProject 的路径是 Mac 下的格式,在 windows 下应该是 src\main\java
。
sqlMapGenerator 标签
该标签用于配置生成 mapper 映射文件的属性,如果没有指定该标签,那么 MBG 将只生成实体类。
它有两个必选属性:
targetPackage
:生成 mapper 文件存放的包名。targetProject
:指定目标项目路径。
示例配置如下:
<sqlMapGenerator targetPackage="test.xml" targetProject="src/main/resources"/>
javaClientGenerator 标签
该标签用于配置 Mapper 接口的属性,如果不配置,不会生成 Mapper 接口。
它有三个必选属性:
type
根据 context 的targetRuntime
的值,分成两类:MyBatis3
ANNOTATEDMAPPER
:基于注解的 Mapper 接口,不会有对应的 xml 映射文件;
MIXEDMAPPER
:xml 和注解的混合形式,上面这种情况中的 SQL Provider 注解方法会被 xml 方式替代。MyBatis3Simple
ANNOTATEDMAPPER
:基于注解的 Mapper 接口,不会有对应的 xml 映射文件;
XMLMAPPER
:所有的方法都在 xml 中,接口调用依赖 xml 文件。(推荐使用)
targetPackage:生成 Mapper 接口存放的包名
- targetProject:指定目标项目路径。
示例配置如下:
<javaClientGenerator type="XMLMAPPER" targetPackage="test.dao" targetProject="src/main/java"/>
table 标签
示例配置如下:
<table tableName="%">
<generatedKey column="id" sqlStatement="MySql"/>
</table>
tableName
指定要生成的表名,% 表示生成全部的表。
generatedKey
用来指定自动生成主键的属性。如果指定这个标签, MBG 将在生成 insert 的 SQL 映射文件中插入一个 selectKe y 标签。
<selectKey keyProperty="id" order="BEFORE" resultType="java.lang.Long">
SELECT LAST_INSERT_ID()
</selectKey>
参考配置示例
<?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="config.properties" />
<context id="MySqlContext" targetRuntime="MyBatis3" defaultModelType="flat">
<property name="beginningDelimiter" value="`"/>
<property name="endingDelimiter" value="`"/>
<commentGenerator type="com.xiaocan.generator.MyCommentGenerator">
<property name="suppressDate" value="true"/>
<property name="addRemarkComments" value="true"/>
</commentGenerator>
<jdbcConnection driverClass="${jdbc.driver}"
connectionURL="jdbc:mysql://localhost:3306/db_mybatis"
userId="${jdbc.username}"
password="${jdbc.password}">
</jdbcConnection>
<javaModelGenerator targetPackage="test.model" targetProject="src/main/java">
<property name="trimStrings" value="true"/>
</javaModelGenerator>
<sqlMapGenerator targetPackage="test.xml" targetProject="src/main/resources"/>
<javaClientGenerator type="XMLMAPPER" targetPackage="test.dao" targetProject="src/main/java"/>
<table tableName="%">
<generatedKey column="id" sqlStatement="MySql"/>
</table>
</context>
</generatorConfiguration>
运行 MBG
package com.xiaocan.generator;
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<>();
// 当生成的代码重复时,覆盖原代码
boolean overwrite = true;
// 读取 MBG 配置文件
InputStream is = Generator.class.getResourceAsStream("/generator/generatorConfig.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);
}
}
}