编写:bravo1988
校审:养兔子的大叔

人总是贪得无厌的…通用Mapper虽然方便,但是仍然要写POJO和Mapper接口,有些公司出于效率考虑,甚至只允许增删改用通用Mapper,查询语句要自己手写。

此时,聪明的程序员不禁想问:有没有办法在建完数据库表的同时,直接生成需要的接口、POJO、XML文件呢?
如果可以,自动生成的文件最好符合以下需求:

  • Mapper接口最好能支持批量操作,比如批量插入、批量删除。
  • POJO最好能搭配Lombok,精简代码。另外最好能有字段注释以及插入后自动返回主键。
  • XML能抽取出BaseResultMap,方便复用

这里介绍一下TkMapper Generator。本质上和MyBatis Generator是一个东西,只不过本次配置是针对通用Mapper的,所以单独拎出来讲讲。

目录结构

image.png

Pom

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <modelVersion>4.0.0</modelVersion>
  6. <groupId>org.example</groupId>
  7. <artifactId>tkMapper-generator</artifactId>
  8. <version>1.0-SNAPSHOT</version>
  9. <properties>
  10. <!-- 版本 -->
  11. <java.version>1.8</java.version>
  12. <tk.mybatis.version>4.1.5</tk.mybatis.version>
  13. <lombok.version>1.16.22</lombok.version>
  14. <mysql.version>5.1.47</mysql.version>
  15. </properties>
  16. <dependencies>
  17. <dependency>
  18. <groupId>mysql</groupId>
  19. <artifactId>mysql-connector-java</artifactId>
  20. <version>${mysql.version}</version>
  21. </dependency>
  22. <dependency>
  23. <groupId>org.projectlombok</groupId>
  24. <artifactId>lombok</artifactId>
  25. <version>${lombok.version}</version>
  26. </dependency>
  27. <dependency>
  28. <groupId>tk.mybatis</groupId>
  29. <artifactId>mapper</artifactId>
  30. <version>${tk.mybatis.version}</version>
  31. </dependency>
  32. </dependencies>
  33. <build>
  34. <plugins>
  35. <!-- mybatis-generator插件 -->
  36. <plugin>
  37. <groupId>org.mybatis.generator</groupId>
  38. <artifactId>mybatis-generator-maven-plugin</artifactId>
  39. <version>1.3.6</version>
  40. <configuration>
  41. <!--允许移动生成的文件 -->
  42. <verbose>true</verbose>
  43. <!-- 是否覆盖 -->
  44. <overwrite>true</overwrite>
  45. <!-- generatorConfig配置文件 -->
  46. <configurationFile>src/main/resources/generatorConfig.xml</configurationFile>
  47. </configuration>
  48. <dependencies>
  49. <dependency>
  50. <groupId>mysql</groupId>
  51. <artifactId>mysql-connector-java</artifactId>
  52. <version>${mysql.version}</version>
  53. </dependency>
  54. <dependency>
  55. <groupId>tk.mybatis</groupId>
  56. <artifactId>mapper</artifactId>
  57. <version>${tk.mybatis.version}</version>
  58. </dependency>
  59. </dependencies>
  60. </plugin>
  61. </plugins>
  62. </build>
  63. </project>

BaseMapper

/**
 * @author bravo
 * @date 2020-01-22 21:00
 * 自定义BaseMapper让子接口继承(我们一般直接继承Mapper<T>,但那个不够强大)
 *
 * Mapper接口:基本的增、删、改、查方法
 * IdListMapper:支持根据IdList批量查询和删除
 * InsertListMapper:支持批量插入
 *
 * 注意,一定要加@RegisterMapper。因为到时要拷贝到项目中,该注解可以让这个接口不参与实例化
 */
@RegisterMapper
public interface BaseMapper<T> extends Mapper<T>, IdListMapper<T, Long>, InsertListMapper<T> {
}

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>

    <context id="DB2Tables" targetRuntime="MyBatis3Simple" defaultModelType="flat">
        <!--
            caseSensitive 是否区分大小写,默认值 false。如果数据库区分大小写,这里就需要配置为 true,这样当表名为 USER 时,会生成 @Table(name = "USER") 注解,否则使用小写 user 时会找不到表。
            forceAnnotation 是否强制生成注解,默认 false,如果设置为 true,不管数据库名和字段名是否一致,都会生成注解(包含 @Table 和 @Column)。
            generateColumnConsts 在生成的 model中,增加字段名的常量,便于使用 Example 拼接查询条件的时候使用。
        -->
        <property name="javaFileEncoding" value="UTF-8"/>

        <!-- beginningDelimiter 和 endingDelimiter 开始和结束分隔符,对于有关键字的情况下适用。 -->
        <property name="beginningDelimiter" value="`"/>
        <property name="endingDelimiter" value="`"/>

        <!-- 是否去除自动生成的注释 true:是 : false:使用默认的(一大坨英文) POJO上的注释内容来自数据库字段的comment-->
        <property name="useMapperCommentGenerator" value="true"/>

        <plugin type="tk.mybatis.mapper.generator.MapperPlugin">
            <!-- mappers 可以使用通用Mapper默认的Mapper接口,这样就不需要自己写BaseMapper。届时自动生成的Mapper接口会继承Mapper<T>而不是BaseMapper -->
            <!--<property name="mappers" value="tk.mybatis.mapper.common.Mapper"/>-->
            <property name="mappers" value="com.bravo.mapper.base.BaseMapper"/>
            <property name="caseSensitive" value="true"/>
            <!-- 为生成的Model增加@Data注解 -->
            <property name="lombok" value="Data"/>
        </plugin>

        <!-- 数据库连接配置 -->
        <jdbcConnection driverClass="com.mysql.jdbc.Driver"
                        connectionURL="jdbc:mysql:///test"
                        userId="root"
                        password="root">

            <!-- mysql 驱动8.x版本需要设置时区 value设置为GMT、UTC都可以 -->
            <property name="serverTimezone" value="GMT"/>

            <!-- 解决生成其他数据库的表的model和mapper等 -->
            <!-- 也可解决生成的model里面缺少@Id注解问题(此问题mysql驱动版本回退到5.1也可以解决)-->
            <property name="nullCatalogMeansCurrent" value="true"/>
        </jdbcConnection>


        <javaTypeResolver>
            <!--
             true:使用BigDecimal对应decimal(小数)和 numeric(数字)数据类型
             false:默认,
                 scale>0;length>18:使用BigDecimal;
                 scale=0;length[10,18]:使用Long;
                 scale=0;length[5,9]:使用Integer;
                 scale=0;length<5:使用Short;
              -->
            <property name="forceBigDecimals" value="false"/>
        </javaTypeResolver>


        <!-- 指定POJO生成的位置-->
        <javaModelGenerator targetPackage="com.bravo.pojo" targetProject="src/main/java">
            <!-- 在targetPackage的基础上,根据数据库的schema再生成一层package,最终生成的类放在这个package下,默认为false -->
            <property name="enableSubPackages" value="true"/>
            <!-- 设置是否在setter方法中,对String类型字段调用trim()方法(如果你用Lombok,忽略这个) -->
            <property name="trimStrings" value="true"/>
        </javaModelGenerator>
        <!-- 指定XML生成的位置-->
        <sqlMapGenerator targetPackage="com.bravo.mapper" targetProject="src/main/resources"/>
        <!-- 指定Mapper接口生成的位置-->
        <javaClientGenerator targetPackage="com.bravo.mapper" targetProject="src/main/java" type="XMLMAPPER"/>

        <!-- table标签中,tableName代表表名 domainObjectName可以指定生成的实体名,不指定的话默认使用表名 -->
        <!-- 要保证表t_superman存在哦~,使用%通配符则可生成符合规则的所有表对应的model、mapper等文件,比sys_%,生成sys_city sys_province... -->
        <table tableName="t_superman">
            <!-- 在Model的id字段时加上@GeneratedValue(...),用于插入后返回主键 -->
            <generatedKey column="id" sqlStatement="MYSQL"/>
            <!-- 如果希望对默认生成的名字进行字符替换,可以使用下方配置。比如:把生成的POJO、Mapper接口、Mapper.xml名字的前缀T去掉(否则t_user 会输出 TUser) -->
            <domainObjectRenamingRule searchString="^T" replaceString="" />
        </table>
        <!--<table tableName="sys_%" />-->
    </context>
</generatorConfiguration>

使用步骤

修改数据库配置

image.png

指定POJO位置

image.png

指定XML位置

image.png

指定Mapper接口位置

image.png

指定操作的表

image.png

双击执行Generator插件

image.png

结果展示

image.png

细节说明

BaseMapper要加@RegisterMapper。
另外BaseMapper继承了IdListMapper和InsertListMapper,支持批量操作。
image.png

@GeneratedValue是因为generatorConfig.xml中配置了:

加上此注解后,新增插入Pojo时数据库会把主键返回到当前POJO。
image.png

最后,也是本文最有用的一句:
在当前工程生成后,把文件拷贝到自己的项目中,包括BaseMapper。但是千万别急着编码,最好再看看改改,不要太相信自动生成。

  • 把类注释写上
  • 修改不合理的字段类型

当然,如果你习惯用JPA,就会发现:干嘛要这么麻烦。SQL?那是啥?

2020-01-23