当前位置: 首页 > 编程笔记 >

MyBatis Generator 自定义生成注释的方法

洪国兴
2023-03-14
本文向大家介绍MyBatis Generator 自定义生成注释的方法,包括了MyBatis Generator 自定义生成注释的方法的使用技巧和注意事项,需要的朋友参考一下

最近做项目,ORM 使用的是 MyBatis,为了偷懒,我自然而然的想到了使用 MyBatis Generator(MBG)来生成数据库表对应的实体代码和 Mapper 代码。于是做了如下的配置(对 MBG 配置不熟悉的同学可以参考 Mybatis Generator最完整配置详解):

<?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>
  <!-- 指定数据库驱动的jdbc驱动jar包的位置 -->
  <classPathEntry location="./mysql-connector-java-5.1.40.jar" />

  <context id="mysql" defaultModelType="hierarchical" targetRuntime="MyBatis3Simple" >
    <!-- 生成的 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"/>

    <!-- 配置数据库连接 -->
    <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/test?characterEncoding=utf-8" userId="root" password="123456">
    </jdbcConnection>

    <!-- 生成实体的位置 -->
    <javaModelGenerator targetPackage="me.mizhoux.model" targetProject="src/main/java">
      <property name="enableSubPackages" value="true"/>
    </javaModelGenerator>

    <!-- 生成 Mapper 接口的位置 -->
    <sqlMapGenerator targetPackage="me.mizhoux.mapper" targetProject="src/main/java">
      <property name="enableSubPackages" value="true"/>
    </sqlMapGenerator>

    <!-- 生成 Mapper XML 的位置 -->
    <javaClientGenerator targetPackage="me.mizhoux.mapper" type="XMLMAPPER" targetProject="src/main/java">
      <property name="enableSubPackages" value="true"/>
    </javaClientGenerator>

    <!-- 设置数据库的表名和实体类名 -->
    <table tableName="t_user" domainObjectName="User">
      <!-- generatedKey用于生成生成主键的方法 -->
      <generatedKey column="id" sqlStatement="SELECT LAST_INSERT_ID()"/>
    </table>

  </context>

</generatorConfiguration>

数据库建库建表的代码:

CREATE SCHEMA `db_test` DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ;

CREATE TABLE `db_test`.`t_user` (
 `id` INT NOT NULL AUTO_INCREMENT COMMENT '用户 ID',
 `username` VARCHAR(30) NULL COMMENT '用户名称',
 `password` VARCHAR(20) NULL COMMENT '用户密码',
 `birthday` DATE NULL COMMENT '用户生日',
 PRIMARY KEY (`id`),
 UNIQUE INDEX `username_UNIQUE` (`username` ASC)
) COMMENT = '用户';

开开心心,执行命令,开始生成代码:

java -jar mybatis-generator-core-1.3.7.jar -configfile generatorConfig.xml -overwrite

然后查看生成的 Java 实体类:

看着这个注释,让我有点纠结啊 —— 为什么不是数据库中每个字段对应的注释呢?查找相关资料,得知 MBG 生成的是由 org.mybatis.generator.api.CommentGenerator 来控制的。这是一个接口,MBG 的默认实现类是做 org.mybatis.generator.internal.DefaultCommentGenerator。当你在 generatorConfig.xml 中配置了 commentGenerator 标签,那么默认状态下,生成注释的工作,将由 DefaultCommentGenerator来完成。 所以我们来查看下这个 DefaultCommentGenerator 的源码:

public class DefaultCommentGenerator implements CommentGenerator {
  // 属性,即配置在 commentGenerator 标签之内的 Property 标签
  private Properties properties;
  // 是否不生成日期
  private boolean suppressDate;
  // 是否不生成注释
  private boolean suppressAllComments;
  // 是否添加数据库内的注释
  private boolean addRemarkComments;
  // 日期格式化
  private SimpleDateFormat dateFormat;

  public DefaultCommentGenerator() {
    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);
    }
  }
  
  // 其他代码
  ...
}

addRemarkComments 这个属性,看来就是用来生成数据库注释用的 —— 好开心,那把它设置为 true 试试:

<generatorConfiguration>
  <!-- 指定数据库驱动的jdbc驱动jar包的位置 -->
  <classPathEntry location="./mysql-connector-java-5.1.40.jar" />
  
  <context id="mysql" defaultModelType="hierarchical" targetRuntime="MyBatis3Simple" >
    <property name="javaFileEncoding" value="UTF-8"/>
    <!-- 其他 Property -->

    <commentGenerator>
      <property name="suppressDate" value="true"/>
      <property name="addRemarkComments" value="true"/>
    </commentGenerator>
    
    ...
  </context>
</generatorConfiguration>

运行命令:

java -jar mybatis-generator-core-1.3.7.jar -configfile generatorConfig.xml -overwrite

数据库注释倒是拿到了,但是生成的一堆其他信息,看着实在是太扎眼了。查看源码,发现这些内容已经写死在 DefaultCommentGenerator 中了,没有办法自定义。

自己动手丰衣足食,我们为啥不自己写个类实现 CommentGenerator 接口,然后自定义自己想要的注释呢。查看 commentGenerator 的 DTD,发现正好 commentGenerator 有个 type 属性,可以用来指定自己的注释实现类:

查看 CommentGenerator 接口,发现里面的方法非常多,不仅包含了生成 Java 实体注释对应的方法,还包括了生成 XML 中注释的方法。所以我们先写一个默认的实现类,实现CommentGenerator 接口,但不做任何操作 —— 因为 DefaultCommentGenerator 本文已经存在了,为了避免混淆,就叫它SimpleCommentGenerator吧。然后定义我们自己的注释类,MySQLCommentGenerator,继承 SimpleCommentGenerator,重写我们需要的方法:

public class MySQLCommentGenerator extends SimpleCommentGenerator {

  private Properties properties;

  public MySQLCommentGenerator() {
    properties = new Properties();
  }

  @Override
  public void addConfigurationProperties(Properties properties) {
    // 获取自定义的 properties
    this.properties.putAll(properties);
  }

  @Override
  public void addModelClassComment(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
    String author = properties.getProperty("author");
    String dateFormat = properties.getProperty("dateFormat", "yyyy-MM-dd");
    SimpleDateFormat dateFormatter = new SimpleDateFormat(dateFormat);

    // 获取表注释
    String remarks = introspectedTable.getRemarks();

    topLevelClass.addJavaDocLine("/**");
    topLevelClass.addJavaDocLine(" * " + remarks);
    topLevelClass.addJavaDocLine(" *");
    topLevelClass.addJavaDocLine(" * @author " + author);
    topLevelClass.addJavaDocLine(" * @date " + dateFormatter.format(new Date()));
    topLevelClass.addJavaDocLine(" */");
  }

  @Override
  public void addFieldComment(Field field, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) {
    // 获取列注释
    String remarks = introspectedColumn.getRemarks();
    field.addJavaDocLine("/**");
    field.addJavaDocLine(" * " + remarks);
    field.addJavaDocLine(" */");
  }
}

因为我们现在要使用到我们自己自定义的 CommentGenerator ,所以我们 通过代码的方式来操作 MBG:

public class Generator {

  public static void main( String[] args ) throws Exception {
    List<String> warnings = new ArrayList<>();
    File configFile = new File("generatorConfig.xml");
    ConfigurationParser cp = new ConfigurationParser(warnings);
    Configuration config = cp.parseConfiguration(configFile);
    DefaultShellCallback callback = new DefaultShellCallback(true);
    MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
    myBatisGenerator.generate(null);
  }

}

然后配置 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>
  <!-- 指定数据库驱动的jdbc驱动jar包的位置 -->
  <!-- 不再需要,因为 jar 包已经在 classpath 中
  <classPathEntry location="./mysql-connector-java-5.1.40.jar" /> 
  -->

  <context id="mysql" defaultModelType="hierarchical" targetRuntime="MyBatis3Simple" >
    ...
    
    <!-- 自定义注释生成器 -->
    <commentGenerator type="me.mizhoux.mbgcomment.MySQLCommentGenerator">
      <property name="author" value="Michael Chow"/>
      <property name="dateFormat" value="yyyy/MM/dd"/>
    </commentGenerator>
    
    ...
  </context>

</generatorConfiguration>

完整的 Maven 项目在 我的 GitHub。现在,我们运行主类 Generator,成功生成了数据库中的注释:

等等,好像有点不对劲!

类的注释怎么没有了!

想来应该是 JDBC 连接 MySQL 的时候需要添加什么属性才能获取表的注释,上网查询,发现是 useInformationSchema,需要将其设置为 true(看来是 MBG 给自己的 DefaultCommentGenerator 开了小灶):

<?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>
  <context id="mysql" defaultModelType="hierarchical" targetRuntime="MyBatis3Simple" >
    ...
    
    <!-- 自定义注释生成器 -->
    <commentGenerator type="me.mizhoux.mbgcomment.MySQLCommentGenerator">
      <property name="author" value="Michael Chow"/>
      <property name="dateFormat" value="yyyy/MM/dd"/>
    </commentGenerator>

    <!-- 配置数据库连接 -->
    <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/test?characterEncoding=utf-8" userId="root" password="123456">
       <!-- 设置 useInformationSchema 属性为 true -->
       <property name="useInformationSchema" value="true" />
    </jdbcConnection>
    
    ...
  </context>
</generatorConfiguration>

然后再次运行主类 Generator:

成功的生成了类主食和字段注释~

我这里并没有处理注释是多行文本的情况 —— 留给有兴趣的读者吧~

小项目地址:https://github.com/mizhoux/mbg-comment

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持小牛知识库。

 类似资料:
  • 我正在编写一个库/sdk,它可以拦截任何使用自定义注释进行注释的方法。代码的工作方式有点像这样 截取这个的方面有一个切入点表达式 当我在与相同的包中描述方面时,此代码工作正常。但是,如果我创建一个单独的库并定义方面,因为它无法拦截。有帮助吗? 回应@Bond的评论 Spring版本:Spring上下文-4.1.7。发布aspectj-1.6.5问题的关键是注释不会在同一个项目中使用。在编译之后,它

  • 在我们的项目中,我们正试图从Spring标准AOP转移到AspectJ,正如在许多类似的地方所解释的那样(我们需要使事务处理成为一些私有和受保护的方法)。 我们已经能够使用标准的Spring注释(如)来很好地完成这项工作。但是我们面临的问题是,在我们的项目中,有一些自定义注释(不是自定义方面)是AeyJ无法识别的。例如,我们有一个注释“扩展”(仅修改属性): 你知道如何告诉AspectJ也给wea

  • 现有的答案很好地解释了如何在方法执行时间日志中使用自定义注释。我想知道是否有办法对类和方法使用相同的注释,但是点切应该在使用它的地方有所不同。 若注释用于类,那个么类中的所有方法都应该考虑在方面类中记录执行时间(比如

  • 我发现了几个与此相关的(不是重复的)问题,但它们不能让我满意。 我无法理解在哪里以及为什么要使用? 我在一本书中读到了一个自定义注释的示例,但没有详细解释。 myMeth()内的输出与预期一致。 关于这个例子,我有几个问题。 1-如何在此程序中使用和?或

  • 问题内容: 注释如何与Java一起使用?以及如何创建这样的自定义注释: 基本上,我需要保留的POJO在持久化时像这样进行序列化: 这样,实际的生成/持久对象是这样的: 任何想法如何实现这一点? 问题答案: 如果创建自定义注释,则必须使用此处的 API 示例进行处理。您可以参考如何声明注释。 这是Java中的示例注释声明的样子。 并被称为。 表示您想在运行时保留注释,并且可以在运行时访问它。 表示您