在文章《MyBatis(二) XML与注解方式基础用法(以RBAC权限管理为例)》中,我们在配置XML文件的数据列和实体属性映射时,是自己一个个写的,这样在数据表字段多的时候很容易出错,因此,需要“偷懒”,MyBatis开发团队也提供了一个代码生成器---generator,它通过各种配置可以生成不同类型的代码,下面来了解一下。
1. 在src\main\resource目录下创建generator子目录,然后其下创建文件generatorConfig.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>
<!-- defaultModelType为flat则每一个表生成一个实体类 -->
<context id="MySqlContext" targetRuntime="MyBatis3Simple" defaultModelType="flat">
<property name="autoDelimitKeywords" value="true"/>
<property name="beginningDelimiter" value="`"/>
<property name="endingDelimiter" value="`"/>
<property name="javaFileEncoding" value="UTF-8"/>
<!-- 配置如何生成注释信息 -->
<commentGenerator type="cn.linjk.mybatistest.generator.MyCommentGenerator">
<!-- 阻止生成的注释包含时间戳 -->
<property name="suppressDate" value="true"/>
<!-- 添加数据表的备注信息 -->
<property name="addRemarkComments" value="true"/>
</commentGenerator>
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/mytest"
userId=""
password="">
</jdbcConnection>
<javaModelGenerator targetPackage="cn.linjk.mybatistest.generator.domain"
targetProject="src\main\java">
<property name="enableSubPackages" value="false"/>
<property name="trimStrings" value="true"/>
</javaModelGenerator>
<sqlMapGenerator targetPackage="cn.linjk.mybatistest.generator.xml"
targetProject="src\main\resources"/>
<javaClientGenerator type="XMLMAPPER" targetPackage="cn.linjk.mybatistest.generator.dao"
targetProject="src\main\java"/>
<table tableName="%">
</table>
</context>
</generatorConfiguration>
2. 产生代码
生成代码有如下几种方式:
1. Java代码
2. 命令行
3. maven插件
4. ide插件,如eclipse
之前用过第三种,现在采用第一种试试。
首先,在pom.xml增加生成器的依赖:
注意到,在generatorConfig.xml的commentGenerator字标签中,我们继承默认的注释生成器实现了自己的注释生成器,这里先实现它:
package cn.linjk.mybatistest.generator;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.dom.java.Field;
import org.mybatis.generator.config.PropertyRegistry;
import org.mybatis.generator.internal.DefaultCommentGenerator;
import org.mybatis.generator.internal.util.StringUtility;
import java.util.Properties;
/**
* 自定义注释生成器
* @author linjk
* @date 2019/02/21
* @version 1.0
*/
public class MyCommentGenerator extends DefaultCommentGenerator {
private boolean suppressAllComments;
private boolean addRemarkComments;
@Override
public void addConfigurationProperties(Properties properties) {
super.addConfigurationProperties(properties);
suppressAllComments = StringUtility.isTrue(properties.getProperty(PropertyRegistry.COMMENT_GENERATOR_SUPPRESS_ALL_COMMENTS));
addRemarkComments = StringUtility.isTrue(properties.getProperty(PropertyRegistry.COMMENT_GENERATOR_ADD_REMARK_COMMENTS));
}
@Override
public void addFieldComment(Field field, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) {
if (suppressAllComments) {
return;
}
field.addJavaDocLine("/**");
String remarks = introspectedTable.getRemarks();
if (addRemarkComments && StringUtility.stringHasValue(remarks)) {
String[] remarkLines = remarks.split(System.getProperty("line.separator"));
for (String remarkLine : remarkLines) {
field.addJavaDocLine(" * " + remarkLine);
}
}
field.addJavaDocLine(" * " + introspectedColumn.getActualColumnName());
field.addJavaDocLine(" */");
}
}
然后实现generator生成器核心代码:
package cn.linjk.mybatistest.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 {
// 代码生成器执行过程中的警告信息
List<String> warnings = new ArrayList<>();
// 当生成的代码重复时,覆盖原代码
boolean overwrite = true;
InputStream inputStream = Generator.class.getResourceAsStream("/generator/generatorConfig.xml");
ConfigurationParser configurationParser = new ConfigurationParser(warnings);
Configuration configuration = configurationParser.parseConfiguration(inputStream);
inputStream.close();
DefaultShellCallback callback = new DefaultShellCallback(overwrite);
MyBatisGenerator myBatisGenerator = new MyBatisGenerator(configuration, callback, warnings);
myBatisGenerator.generate(null);
for (String warning : warnings) {
System.out.println(warning);
}
}
}
后面需要重新生成时,运行这个类的main函数即可。
3. 运行结果
可以看到,也生成了通用的CRUD代码。
4. 踩坑
我们在TUserMapper.java增加一个接口:
重新执行代码生成看看:
我们写的代码被覆盖了,这样努力岂不是付诸东流了?我们注意到,生成的代码都有@mbggenerated标记:
这个标记的含义是被标记的字段或方法是自动生成,重新生成会被覆盖,即使其他字段或方法没有这个标记都会被覆盖,目前要恢复被覆盖的方法,只能通过版本管理工具来复制粘贴了,找了几种方式,在IDEA里都不行,又说到eclipse有一个插件可以合并,但是没用eclipse,就没事了,后面找到好的实现方案再补充了。
目前,想到的一种可用的方式如下:
就是生成的文件不动,文件名增加一个自定义的后缀,如“_extends”,但是mapper的namespace一致,然后在这个文件写自己的业务SQL语句,与生成的文件独立,这样变与不变就分割开了。