tags: [mybatis, mybatis generator]
categories: [mybatis]


前言

实际开发之中,虽然有很多CRUD工具,但是使用最多的还是Mybatis,而Mybatis Gerator可以帮助你自动生成基本的单表CRUD代码,提高效率

但是生成的代码有些地方已经不符合当前的风格和标准,比如现在很多项目都是使用lombok,而不是在实体类里面添加get/set方法,默认生成的注释信息不友好,这个时候我们可以通过一些修改来生成我们想要的结果

本项目为SpringBoot项目,数据为MySQL

使用

引入依赖

后边的Plugn是以Maven生成的,若以代码形式来生成则无需配置

  1. <!--mybatis-->
  2. <dependency>
  3. <groupId>org.mybatis.spring.boot</groupId>
  4. <artifactId>mybatis-spring-boot-starter</artifactId>
  5. </dependency>
  6. <!-- https://mvnrepository.com/artifact/org.mybatis.generator/mybatis-generator-core -->
  7. <dependency>
  8. <groupId>org.mybatis.generator</groupId>
  9. <artifactId>mybatis-generator-core</artifactId>
  10. <version>1.3.7</version>
  11. </dependency>
  12. <plugin>
  13. <groupId>org.mybatis.generator</groupId>
  14. <artifactId>mybatis-generator-maven-plugin</artifactId>
  15. <version>1.3.7</version>
  16. <configuration>
  17. <!--自定义路径,否则会自动识别GeneratorConfig.xml文件-->
  18. <!-- <configurationFiile>${basedir}/src/main/resources/generatorConfig.xml</configurationFile>-->
  19. <!--是为了运行mvn mybatis-generator:generate -e时显示具体过程-->
  20. <verbose>true</verbose>
  21. <!--为了生成文件时后一次生成的文件覆盖前一次生成的同名文件-->
  22. <overwrite>true</overwrite>
  23. </configuration>
  24. <dependencies>
  25. <dependency>
  26. <groupId>mysql</groupId>
  27. <artifactId>mysql-connector-java</artifactId>
  28. <version>5.1.44</version>
  29. </dependency>
  30. </dependencies>
  31. </plugin>

后边的Plugn是以Maven生成需要配置的,若以代码形式来生成则无需配置
我的存放目录如下
1.png

添加自定义插件

  1. package com.bwensun.common.mybatis;
  2. import org.mybatis.generator.api.IntrospectedColumn;
  3. import org.mybatis.generator.api.IntrospectedTable;
  4. import org.mybatis.generator.api.PluginAdapter;
  5. import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
  6. import org.mybatis.generator.api.dom.java.Interface;
  7. import org.mybatis.generator.api.dom.java.Method;
  8. import org.mybatis.generator.api.dom.java.TopLevelClass;
  9. import java.text.SimpleDateFormat;
  10. import java.util.Date;
  11. import java.util.List;
  12. /**
  13. * lombok插件
  14. *
  15. * @author bwensun
  16. * @date 2019/12/16
  17. */
  18. public class LombokPlugin extends PluginAdapter {
  19. @Override
  20. public boolean validate(List<String> warnings) {
  21. return true;
  22. }
  23. @Override
  24. public boolean clientGenerated(Interface interfaze, TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
  25. SimpleDateFormat dateFormatter = new SimpleDateFormat(properties.getProperty("dateFormat", "yyyy-MM-dd"));
  26. //接口添加注释
  27. interfaze.addJavaDocLine("/**");
  28. interfaze.addJavaDocLine(" * " + introspectedTable.getRemarks());
  29. interfaze.addJavaDocLine(" *");
  30. interfaze.addJavaDocLine(" * @author " + properties.getProperty("author"));
  31. interfaze.addJavaDocLine(" * @date " + dateFormatter.format(new Date()));
  32. interfaze.addJavaDocLine(" */");
  33. //dao添加注解
  34. addAnnotations(interfaze, "org.springframework.stereotype.Repository", "@Repository");
  35. return true;
  36. }
  37. @Override
  38. public boolean modelBaseRecordClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
  39. if (Boolean.parseBoolean(this.properties.getProperty("data"))) {
  40. addAnnotations(topLevelClass, "lombok.Data", "@Data");
  41. } else {
  42. addAnnotations(topLevelClass, "lombok.Getter", "@Getter");
  43. addAnnotations(topLevelClass, "lombok.Setter", "@Setter");
  44. addAnnotations(topLevelClass, "lombok.ToString", "@ToString");
  45. }
  46. if (Boolean.parseBoolean(this.properties.getProperty("builder"))) {
  47. addAnnotations(topLevelClass, "lombok.Builder", "@Builder");
  48. }
  49. return true;
  50. }
  51. /**
  52. * 关闭get方法生成
  53. */
  54. @Override
  55. public boolean modelGetterMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn, IntrospectedTable introspectedTable, ModelClassType modelClassType) {
  56. return false;
  57. }
  58. /**
  59. * 关闭set方法生成
  60. */
  61. @Override
  62. public boolean modelSetterMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn, IntrospectedTable introspectedTable, ModelClassType modelClassType) {
  63. return false;
  64. }
  65. public void addSwaggerAnnotation(){
  66. }
  67. /**
  68. * 设置类注解
  69. *
  70. * @param importedType 导包类型
  71. * @param annotation 注解
  72. */
  73. private void addAnnotations(TopLevelClass topLevelClass, String importedType, String annotation) {
  74. topLevelClass.addImportedType(importedType);
  75. topLevelClass.addAnnotation(annotation);
  76. }
  77. /**
  78. * 设置接口注解
  79. *
  80. * @param importedType 导包类型
  81. * @param annotation 注解
  82. */
  83. private void addAnnotations(Interface interfaze, String importedType, String annotation) {
  84. interfaze.addImportedType(new FullyQualifiedJavaType(importedType));
  85. interfaze.addAnnotation(annotation);
  86. }
  87. private String date2Str(Date date) {
  88. SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd");
  89. return format.format(date);
  90. }
  91. }

说明
Mybatis Generator的配置文件中包含了plugn标签,我们就可以通过手写插件来实现我们自己的功能,

重写注释部分注释方法

  1. package com.bwensun.common.mybatis;
  2. import org.mybatis.generator.api.IntrospectedColumn;
  3. import org.mybatis.generator.api.IntrospectedTable;
  4. import org.mybatis.generator.api.dom.java.*;
  5. import org.mybatis.generator.internal.DefaultCommentGenerator;
  6. import org.mybatis.generator.internal.util.StringUtility;
  7. import java.text.SimpleDateFormat;
  8. import java.util.Date;
  9. import java.util.List;
  10. import java.util.Properties;
  11. import java.util.Set;
  12. /**
  13. * 增加 swagger 字段注释支持
  14. *
  15. * @author daiwenzh5
  16. * @date 2019/9/8 18:56
  17. */
  18. public class CustomCommentGenerator extends DefaultCommentGenerator {
  19. private Properties properties;
  20. public CustomCommentGenerator() {
  21. properties = new Properties();
  22. }
  23. @Override
  24. public void addConfigurationProperties(Properties properties) {
  25. // 获取自定义的 properties
  26. this.properties.putAll(properties);
  27. }
  28. /**
  29. * 添加 swagger 字段注解
  30. *
  31. * @param field 字段
  32. * @param introspectedTable 表
  33. * @param introspectedColumn 列
  34. * @param imports 导入类
  35. */
  36. @Override
  37. public void addFieldAnnotation(Field field, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn, Set<FullyQualifiedJavaType> imports) {
  38. imports.add(new FullyQualifiedJavaType("io.swagger.annotations.ApiModelProperty"));
  39. String remarks = introspectedColumn.getRemarks();
  40. field.addAnnotation(this.getSwaggerAnnotation(field.getName(), remarks));
  41. super.addFieldAnnotation(field, introspectedTable, introspectedColumn, imports);
  42. }
  43. @Override
  44. public void addFieldAnnotation(Field field, IntrospectedTable introspectedTable, Set<FullyQualifiedJavaType> set) {
  45. super.addFieldAnnotation(field, introspectedTable, set);
  46. }
  47. @Override
  48. public void addFieldComment(Field field, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) {
  49. // 获取字段注释
  50. String remarks = introspectedColumn.getRemarks();
  51. field.addJavaDocLine("/**");
  52. field.addJavaDocLine(" * " + remarks);
  53. field.addJavaDocLine(" */");
  54. }
  55. @Override
  56. public void addGeneralMethodComment(Method method, IntrospectedTable introspectedTable) {
  57. /* if (suppressAllComments) {
  58. return;
  59. }*/
  60. String methodDoc = getMethodDoc(method, introspectedTable);
  61. method.addJavaDocLine("/**");
  62. method.addJavaDocLine(" * " + methodDoc);
  63. method.addJavaDocLine(" *");
  64. setMethodParam(method);
  65. setMethodReturn(method, introspectedTable);
  66. method.addJavaDocLine(" */");
  67. }
  68. @Override
  69. public void addClassAnnotation(InnerClass innerClass, IntrospectedTable introspectedTable, Set<FullyQualifiedJavaType> set) {
  70. super.addClassAnnotation(innerClass, introspectedTable, set);
  71. }
  72. @Override
  73. public void addModelClassComment(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
  74. String author = properties.getProperty("author");
  75. String dateFormat = properties.getProperty("dateFormat", "yyyy-MM-dd");
  76. SimpleDateFormat dateFormatter = new SimpleDateFormat(dateFormat);
  77. // 获取表注释
  78. String remarks = introspectedTable.getRemarks();
  79. topLevelClass.addJavaDocLine("/**");
  80. topLevelClass.addJavaDocLine(" * " + remarks);
  81. topLevelClass.addJavaDocLine(" *");
  82. topLevelClass.addJavaDocLine(" * @author " + author);
  83. topLevelClass.addJavaDocLine(" * @date " + dateFormatter.format(new Date()));
  84. topLevelClass.addJavaDocLine(" */");
  85. }
  86. /**
  87. * 获取 swagger 注解信息
  88. *
  89. * @param name 字段名
  90. * @param remarks 注释信息
  91. * @return 返回 swagger 注释字符串
  92. */
  93. private String getSwaggerAnnotation(String name, String remarks) {
  94. StringBuffer buffer = new StringBuffer("@ApiModelProperty(");
  95. buffer.append("name = \"");
  96. buffer.append(name);
  97. if (StringUtility.stringHasValue(remarks)) {
  98. buffer.append("\", value = \"");
  99. buffer.append(remarks);
  100. }
  101. buffer.append("\")");
  102. return buffer.toString();
  103. }
  104. private String getMethodDoc(Method method, IntrospectedTable introspectedTable) {
  105. String remarks = introspectedTable.getRemarks();
  106. String methodDoc;
  107. switch (method.getName()){
  108. case "deleteByPrimaryKey":
  109. methodDoc = ("根据主键删除" + remarks + "记录");
  110. break;
  111. case "selectByPrimaryKey":
  112. methodDoc = ("根据主键查询" + remarks + "记录");
  113. break;
  114. case "insert":
  115. methodDoc = ("新增记录至" + remarks);
  116. break;
  117. case "selectAll":
  118. methodDoc = ("查询" + remarks + "所有记录");
  119. break;
  120. case "updateByPrimaryKey":
  121. methodDoc = ("根据主键更新" + remarks + "记录");
  122. break;
  123. default:
  124. methodDoc = "description";
  125. break;
  126. }
  127. return methodDoc;
  128. }
  129. /**
  130. * 设置参数注释
  131. *
  132. * @param method 方法
  133. */
  134. private void setMethodParam(Method method) {
  135. List<Parameter> parameters = method.getParameters();
  136. if (parameters.size() != 0){
  137. parameters.forEach(x ->
  138. method.addJavaDocLine(" * @param " + x.getName() + ("ID".equalsIgnoreCase(x.getName())?" 主键":" 记录") )
  139. );
  140. }
  141. }
  142. /**
  143. * 设置返回值注释
  144. *
  145. * @param method 方法
  146. * @param introspectedTable 表对象
  147. */
  148. private void setMethodReturn(Method method, IntrospectedTable introspectedTable) {
  149. String methodReturn;
  150. String shortName = method.getReturnType().getShortName();
  151. if ("int".equalsIgnoreCase(shortName)){
  152. methodReturn = "受影响的记录数";
  153. }else if (shortName.startsWith("java.util.List")){
  154. methodReturn = introspectedTable.getRemarks() + "list";
  155. }else {
  156. methodReturn = introspectedTable.getRemarks() + "记录";
  157. }
  158. method.addJavaDocLine(" * @return " + methodReturn);
  159. }
  160. }

配置文件配置

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE generatorConfiguration
  3. PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
  4. "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
  5. <generatorConfiguration>
  6. <!-- 数据库驱动:选择你的本地硬盘上面的数据库驱动包-->
  7. <classPathEntry location="D:\ProgramFile\maven\maven_repository\mysql\mysql-connector-java\5.1.44\mysql-connector-java-5.1.44.jar"/>
  8. <context id="CustomGenerator" defaultModelType="hierarchical" targetRuntime="MyBatis3Simple">
  9. <property name="autoDelimitKeywords" value="false"/>
  10. <plugin type="org.mybatis.generator.plugins.SerializablePlugin"/>
  11. <!-- 插件 -->
  12. <plugin type="com.bwensun.common.mybatis.LombokPlugin">
  13. <property name="author" value="bwensun"/>
  14. <property name="builder" value="false"/>
  15. <property name="data" value="false"/>
  16. </plugin>
  17. <commentGenerator type = "com.bwensun.common.mybatis.CustomCommentGenerator">
  18. <property name="javaFileEncoding" value="UTF-8"/>
  19. <property name="suppressDate" value="true" />
  20. <property name="suppressAllComments" value="false" />
  21. <property name="author" value="郑建雄"/>
  22. <property name="dateFormat" value="yyyy/MM/dd"/>
  23. </commentGenerator>
  24. <!--数据库链接URL,用户名、密码 -->
  25. <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://127.0.0.1:3306/blog?useSSL=true"
  26. userId="root" password="285413">
  27. <property name="useInformationSchema" value="true" />
  28. </jdbcConnection>
  29. <javaTypeResolver>
  30. <property name="forceBigDecimals" value="false"/>
  31. </javaTypeResolver>
  32. <!-- 生成模型的包名和位置-->
  33. <javaModelGenerator targetPackage="com.bwensun.blog.domain" targetProject="BLOG_API/src/main/java">
  34. <!-- 是否允许子包,即targetPackage.schemaName.tableName -->
  35. <property name="enableSubPackages" value="true"/>
  36. <!-- 是否对model添加 构造函数 -->
  37. <property name="constructorBased" value="false"/>
  38. <!-- 是否对类CHAR类型的列的数据进行trim操作 -->
  39. <property name="trimStrings" value="true"/>
  40. <!-- 建立的Model对象是否 不可改变 即生成的Model对象不会有 setter方法,只有构造方法 -->
  41. <!--<property name="immutable" value="false"/>-->
  42. </javaModelGenerator>
  43. <!-- 生成映射文件的包名和位置-->
  44. <sqlMapGenerator targetPackage="mapper" targetProject="BLOG_USER_SERVICE/src/main/resources">
  45. <property name="enableSubPackages" value="false"/>
  46. </sqlMapGenerator>
  47. <!-- 生成DAO的包名和位置-->
  48. <javaClientGenerator type="XMLMAPPER" targetPackage="com.bwensun.repository"
  49. targetProject="BLOG_USER_SERVICE/src/main/java">
  50. <property name="enableSubPackages" value="false"/>
  51. </javaClientGenerator>
  52. <!-->要生成的表 tableName是数据库中的表名或视图名 domainObjectName是实体类名<-->
  53. <table tableName="USER" domainObjectName="User" enableCountByExample="false" enableUpdateByExample="false"
  54. enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false">
  55. </table>
  56. </context>
  57. </generatorConfiguration>

执行生成代码

  1. /**
  2. * @author bwensun
  3. * @date 2019/12/17
  4. */
  5. public class MybatisGenerator {
  6. public static void main(String[] args) {
  7. String path = "D:\\ProgramFile\\idea_workspace\\DUBBO_TEST\\BLOG\\BLOG_USER_SERVICE\\src\\main\\resources\\generatorConfig.xml";
  8. args = new String[]{"-configfile", path, "-overwrite"};
  9. ShellRunner.main(args);
  10. }
  11. }