MyBatis generator - 简单使用(3)- 自定义注释

本文档详细介绍了如何使用MyBatisGenerator(MBG)自定义注释生成器,包括配置注释生成器的属性、创建自定义CommentGenerator实现类,以及展示自定义注释在实体类、DAO和XML文件中的应用效果。内容涵盖了MBG的基本配置、注释配置以及自定义注释生成器的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、官方相关文档

  • 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支持的配置:

属性名默认值描述
suppressAllCommentsfalse是否不生成注释,默认false,也就是生成注释
suppressDatefalse是否不生成时间,默认false,也就是注释
addRemarkCommentsfalse是否在实体类的字段上生成对应表列的注释,若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)生成的文件如下:
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值