一、官方相关文档
- github:https://github.com/mybatis/generator
- 文档:http://mybatis.org/generator/index.html
二、自定义注释
在上一篇博客(MyBatis generator - 简单使用(2)- 配置详解)的3.2节说过一个<commentGenerator>
标签,用于自定义注释的生成。
MyBatis generator中默认的注释生成器:org.mybatis.generator.internal.DefaultCommentGenerator
:
- 一般情况下使用默认的注释生成器即可,再结合
commentGenerator
标签进行一些配置 - 若需要完全按照自己想要的方式生成注释,则需要自定义注释生成器
2.1 commentGenerator标签
属性 | 必填 | 描述 |
---|---|---|
type | 否 | 注释器类型,默认DefaultCommentGenerator ,自定义的注释器需要实现org.mybatis.generator.api.CommentGenerator ,且需要有一个public的无参构造方法 |
(2)子标签:仅支持<property>
(3)property支持的配置:
属性名 | 默认值 | 描述 |
---|---|---|
suppressAllComments | false | 是否不生成注释,默认false,也就是生成注释 |
suppressDate | false | 是否不生成时间,默认false,也就是注释 |
addRemarkComments | false | 是否在实体类的字段上生成对应表列的注释,若suppressAllComments=true,则该属性被忽略 |
dateFormat | 注释时间戳格式,用于构造java.text.SimpleDateFormat ,例如:yyyy-MM-dd HH:mm:ss。若suppressAllComments=true,则该属性被忽略 |
示例:
<commentGenerator>
<property name="suppressAllComments" value="false"/>
<property name="suppressDate" value="false"/>
<property name="addRemarkComments" value="true"/>
<property name="dateFormat" value="yyyy/MM/dd HH:mm"/>
</commentGenerator>
生成的实体类如下图所示:
生成的Dao如下图所示:
生成的XML如下图所示:
2.2 自定义注释器
由2.1节可知,可以生成器生成注释,但是生成的注释一般不符合规定,所以我们需要自定义注释生成的样式。
由文档可以知道,MBG(MyBatis Generator的简称)支持自定义注释器,需要以下配置:
- 实现
org.mybatis.generator.api.CommentGenerator
接口 - 提供一个public的无参构造方法
注:MBG使用的是org.mybatis.generator.internal.DefaultCommentGenerator
作为默认的注释生成器,我们也可以通过继承该类进行覆盖相对应的方法进行一些定制化操作。
下面我们就实现CommentGenerator
接口来实现一个符合公司规范的注释生成器(参考DefaultCommentGenerator
)
-
需求:
- 实体类:生成版权、类注释、参数注释,类上添加注解并导包
- Dao:生成版权、类注释、方法注释
- XML:不生成注释
-
注:
- 实体类由
org.mybatis.generator.codegen.mybatis3.model.BaseRecordGenerator
生成 - Dao由
org.mybatis.generator.codegen.mybatis3.javamapper.JavaMapperGenerator
生成
- 实体类由
(1)MBG配置
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"src/main/org/mybatis/generator/config/xml/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<context id="context1" targetRuntime="MyBatis3" >
<!-- 分隔数据库关键词 -->
<property name="autoDelimitKeywords" value="true"/>
<property name="beginningDelimiter" value="`"/>
<property name="endingDelimiter" value="`"/>
<!-- 注释配置 -->
<!-- 自定义注释生成器:MyCommentGenerator -->
<commentGenerator type="com.momo.test.config.MyCommentGenerator">
<property name="suppressAllComments" value="false"/>
<property name="suppressDate" value="false"/>
<property name="addRemarkComments" value="true"/>
<property name="dateFormat" value="yyyy/MM/dd HH:mm"/>
</commentGenerator>
<!-- 2.修改mysql 数据源 -->
<jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://127.0.0.1:3306/test"
userId="root" password="root"/>
<!-- 3.修改model、Dao、Mapper存放目录 -->
<!-- po -->
<javaModelGenerator targetPackage="com.momo.test.order.po" targetProject="src/main/java">
<property name="trimStrings" value="true" />
</javaModelGenerator>
<!-- xml -->
<sqlMapGenerator targetPackage="com.momo.test.mapper" targetProject="src/main/java">
</sqlMapGenerator>
<!-- mapper,type:ANNOTATEDMAPPER、MIXEDMAPPER、XMLMAPPER -->
<javaClientGenerator targetPackage="com.momo.test.order.mapper" targetProject="src/main/java" type="XMLMAPPER">
</javaClientGenerator>
<!-- 4.填写表名和实体类名 -->
<table tableName="product_item" domainObjectName="ProductItem"
delimitIdentifiers="true" delimitAllColumns="false"
enableCountByExample="false" enableDeleteByExample="false"
enableSelectByExample="false" enableUpdateByExample="false">
<property name="trimStrings" value="true"/>
<!-- 获取自增主键 -->
<generatedKey column="id" sqlStatement="MySql"/>
</table>
</context>
</generatorConfiguration>
(2)自定义注释生成器
由下面的MyCommentGenerator类可知,有些自定义操作不受MBG支持,例如添加Dao的注释、不生成实体类getter、setter方法等,只能简单做些自定义操作,所以需要在源码上修改下才可以支持。
import org.mybatis.generator.api.CommentGenerator;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.dom.java.*;
import org.mybatis.generator.api.dom.kotlin.KotlinFile;
import org.mybatis.generator.api.dom.xml.XmlElement;
import org.mybatis.generator.config.PropertyRegistry;
import org.mybatis.generator.internal.util.StringUtility;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;
import java.util.Set;
import static org.mybatis.generator.internal.util.StringUtility.isTrue;
/**
* 自定义注释生成器
*
* @author MQG
* @date 2021/04/25
*/
public class MyCommentGenerator implements CommentGenerator {
private Properties properties;
private boolean suppressDate;
private boolean suppressAllComments;
private boolean addRemarkComments;
private SimpleDateFormat dateFormat;
public MyCommentGenerator() {
super();
properties = new Properties();
suppressDate = false;
suppressAllComments = false;
addRemarkComments = false;
}
@Override
public void addConfigurationProperties(Properties properties) {
this.properties.putAll(properties);
suppressDate = isTrue(properties.getProperty(PropertyRegistry.COMMENT_GENERATOR_SUPPRESS_DATE));
suppressAllComments = isTrue(properties.getProperty(PropertyRegistry.COMMENT_GENERATOR_SUPPRESS_ALL_COMMENTS));
addRemarkComments = isTrue(properties.getProperty(PropertyRegistry.COMMENT_GENERATOR_ADD_REMARK_COMMENTS));
String dateFormatString = properties.getProperty(PropertyRegistry.COMMENT_GENERATOR_DATE_FORMAT);
if (StringUtility.stringHasValue(dateFormatString)) {
dateFormat = new SimpleDateFormat(dateFormatString);
}
}
/**
* Java文件注释(一般用于生成版权信息)
*/
@Override
public void addJavaFileComment(CompilationUnit compilationUnit) {
// 版权信息
compilationUnit.addFileCommentLine("/*");
compilationUnit.addFileCommentLine(" * Copyright © SSY All Rights Reserved.");
compilationUnit.addFileCommentLine(" */");
// Dao类注释
// 由于MBG没有给Dao生成方类注释,所以这里折中一下,在添加类文件注释时生成下Dao的注释
// JavaMapperGenerator中没有调用addClassComment()方法
if (compilationUnit instanceof Interface) {
Interface tInterface = (Interface) compilationUnit;
tInterface.addJavaDocLine("/**");
// 这里写死了注释内容,主要是没法获取到表的注释,如商品信息表
tInterface.addJavaDocLine(" * 商品信息Dao");
tInterface.addJavaDocLine(" *");
tInterface.addJavaDocLine(" * @author MQG");
tInterface.addJavaDocLine(" * @date " + getDateString());
tInterface.addJavaDocLine(" */");
}
}
/**
* 类注释
*/
@Override
public void addClassComment(InnerClass innerClass, IntrospectedTable introspectedTable) {
}
@Override
public void addClassComment(InnerClass innerClass, IntrospectedTable introspectedTable, boolean markAsDoNotDelete) {
}
/**
* 类注解
*/
@Override
public void addClassAnnotation(InnerClass innerClass, IntrospectedTable introspectedTable, Set<FullyQualifiedJavaType> imports) {
// 实体类添加 @Data、@Builder、@NoArgsConstructor、@AllArgsConstructor注解
// 这里比较尴尬的是BaseRecordGenerator类没有配置不生成getter、setter方法的入口,所以@Data就不需要了
if (innerClass instanceof TopLevelClass) {
TopLevelClass topLevelClass = (TopLevelClass) innerClass;
topLevelClass.addImportedType(new FullyQualifiedJavaType("lombok.Data"));
topLevelClass.addImportedType(new FullyQualifiedJavaType("lombok.Builder"));
topLevelClass.addImportedType(new FullyQualifiedJavaType("lombok.NoArgsConstructor"));
topLevelClass.addImportedType(new FullyQualifiedJavaType("lombok.AllArgsConstructor"));
topLevelClass.addAnnotation("@Data");
topLevelClass.addAnnotation("@Builder");
topLevelClass.addAnnotation("@NoArgsConstructor");
topLevelClass.addAnnotation("@AllArgsConstructor");
}
}
/**
* 实体类的注释
*/
@Override
public void addModelClassComment(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
if (suppressAllComments || !addRemarkComments) {
return;
}
// 实体类注释
// BaseRecordGenerator类没有调用addClassComment()方法,调用了addModelClassComment(),所以在这里添加实体类的注释
topLevelClass.addJavaDocLine("/**");
// 这里写死了注释内容,没法获取到表的注释(???),如商品信息表
// 可以找到表名,如product_item
topLevelClass.addJavaDocLine(" * 商品信息(表:" + introspectedTable.getFullyQualifiedTable() + ")");
topLevelClass.addJavaDocLine(" *");
topLevelClass.addJavaDocLine(" * @author MQG");
topLevelClass.addJavaDocLine(" * @date " + getDateString());
topLevelClass.addJavaDocLine(" */");
// 添加实体类的注解
// 因为MBG没有给普通实体类生成注解,所以这里手动调用一下
// BaseRecordGenerator类没有调用addClassAnnotation()
addClassAnnotation(topLevelClass, introspectedTable, null);
}
/**
* 实体类字段注释
*/
@Override
public void addFieldComment(Field field, IntrospectedTable introspectedTable,
IntrospectedColumn introspectedColumn) {
if (suppressAllComments) {
return;
}
field.addJavaDocLine("/**");
field.addJavaDocLine(" * " + introspectedColumn.getRemarks());
field.addJavaDocLine(" */");
}
@Override
public void addFieldComment(Field field, IntrospectedTable introspectedTable) {
}
/**
* 通用方法注释
*
* <p>如Dao中的方法
*/
@Override
public void addGeneralMethodComment(Method method, IntrospectedTable introspectedTable) {
}
/**
* getter方法的注释
*/
@Override
public void addGetterComment(Method method, IntrospectedTable introspectedTable,
IntrospectedColumn introspectedColumn) {
}
/**
* setter方法的注释
*/
@Override
public void addSetterComment(Method method, IntrospectedTable introspectedTable,
IntrospectedColumn introspectedColumn) {
}
@Override
public void addEnumComment(InnerEnum innerEnum, IntrospectedTable introspectedTable) {
}
@Override
public void addGeneralMethodAnnotation(Method method, IntrospectedTable introspectedTable,
Set<FullyQualifiedJavaType> imports) {
}
@Override
public void addGeneralMethodAnnotation(Method method, IntrospectedTable introspectedTable,
IntrospectedColumn introspectedColumn, Set<FullyQualifiedJavaType> imports) {
}
@Override
public void addFieldAnnotation(Field field, IntrospectedTable introspectedTable,
Set<FullyQualifiedJavaType> imports) {
}
@Override
public void addFieldAnnotation(Field field, IntrospectedTable introspectedTable,
IntrospectedColumn introspectedColumn, Set<FullyQualifiedJavaType> imports) {
}
@Override
public void addFileComment(KotlinFile kotlinFile) {
}
@Override
public void addComment(XmlElement xmlElement) {
}
@Override
public void addRootComment(XmlElement rootElement) {
}
/**
* 返回一个格式化日期
*
* @return
*/
protected String getDateString() {
if (suppressDate) {
return null;
} else if (dateFormat != null) {
return dateFormat.format(new Date());
} else {
return new Date().toString();
}
}
}
(3)生成的文件如下: