1. 为什么每个MyBatis项目都需要一个代码生成器
先聊一个很现实的问题:你写一个CRUD接口需要多久?
我见过太多团队,建完表之后,实体类手动敲一遍,Mapper接口手写一遍,XML映射文件再手写一遍,单表操作这几个文件加起来少说两三百行。如果是几十张表,光这些重复劳动就能耗掉一两天,而且枯燥到极点——复制粘贴改字段名,最容易出错的地方恰恰就是这种机械劳动。
mybatis-generator(简称MBG)就是来干掉这个重复过程的。它是MyBatis官方提供的代码生成工具,连接数据库之后,读取表结构信息,自动生成对应实体类、Mapper接口、XML映射文件,甚至连基本的增删改查方法都帮你写好了。2021年的版本(1.4.0及之后)在底层做了不少调整,比如支持了JSR-310时间类型、生成注释策略也变了,网上很多老教程放在今天已经跑不通了,这也是我写这篇笔记的原因。
这工具适合谁?两类人最需要。一类是刚接触MyBatis不久的新手,与其对着几百行XML手敲练指法,不如让生成器把标准写法打出来,你再去研究它为什么长这样,学习效率反而更高;另一类是维护老项目的开发,表结构一变,几分钟内重新生成增量代码,比手动改几十处要靠谱得多。
这篇笔记我会从零开始,把配置、运行、结果解读、踩坑排查完整过一遍,所有操作都是我本地实测过的,尽量做到你照着也能跑通。
2. 整体思路与方案选型
2.1 为什么选择官方生成器,而不是其他插件
MyBatis生态里代码生成方案其实不少,除了官方MBG,还有MyBatis-Plus自带的生成器、MyBatis Generator逆向工程等第三方封装。我做技术选型时更偏向官方工具,核心原因有三个。
第一个是版本跟随紧密。官方MBG随MyBatis框架同步迭代,数据库类型支持、JDBC驱动兼容性都是跟得最紧的。像2021年之后MyBatis 3.5.x普及,很多第三方生成器因为维护滞后,生成的XML里还是老旧的useGeneratedKeys写法,而官方MBG在新版本里已经默认处理得比较合理了。
第二个是配置透明可控。MBG的XML配置文件虽然初次看有点繁琐,但每一个标签都有明确定义,生成什么不生成什么完全由你决定。不像某些封装好的生成器,把配置藏在代码里,出了问题不好排查。
第三个是通用性好。它不绑定任何MyBatis增强框架,生成出来的就是标准MyBatis代码,无论是纯MyBatis、MyBatis-Plus还是Spring Boot集成,都能直接使用或改造。选了它,后续切换框架也不会被锁死。
2.2 两种主流的运行方式对比
MBG有几种运行方式:命令行方式、Maven插件方式、Ant Task方式、Java编程方式。对于日常开发,我用得最多的是Maven插件方式和Java编程方式,命令行方式更多是为了快速验证配置。
Maven插件方式的优势是集成度最高,在pom.xml里配置好插件后,一条mvn mybatis-generator:generate命令就能跑完全流程。它天然适配多模块项目,不需要额外管理jar包,插件会自动拉取依赖。缺点是如果想在生成前后做定制化处理,比如生成后自动调整包路径,就需要额外挂exec-maven-plugin。
Java编程方式的优势是灵活,你可以把生成流程封装成一个工具类,在测试类里右键运行,或者直接集成到自动化构建脚本里。在配置复杂的场景下,比如需要动态传入数据库连接信息、按表名批量生成,Java方式明显更有优势。
我个人的建议是:项目已经用了Maven,优先用Maven插件方式,因为配置简单,团队协作时只要同步pom文件即可;如果只是偶尔用一次,或者需要频繁调整参数,就用Java方式跑一个main方法。后面第三章会分别给出两种方式的完整配置,你可以直接抄作业。
3. Maven插件方式实操(推荐)
3.1 创建测试环境与依赖准备
先用一个最简单的场景练手。假设数据库里有一张用户表t_user,字段包括主键id、用户名username、密码password、邮箱email、创建时间create_time。先建好一张测试表,数据随便插几条就行。
在pom.xml里做两件事:引入MyBatis依赖,配置MBG插件。插件配置是核心,版本号我强烈建议用1.4.0以上版本——这个版本之后生成代码支持了JSR-310日期类型,不会再把数据库的datetime类型生成成Date,而是自动对应LocalDateTime,省去手动转换的麻烦。
<build> <plugins> <plugin> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-maven-plugin</artifactId> <version>1.4.1</version> <configuration> <!-- 配置文件路径 --> <configurationFile>src/main/resources/generatorConfig.xml</configurationFile> <!-- 允许覆盖生成的XML文件 --> <overwrite>true</overwrite> <!-- 打印生成日志 --> <verbose>true</verbose> </configuration> <dependencies> <!-- 数据库驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.28</version> </dependency> </dependencies> </plugin> </plugins> </build>这里有两个细节要说明。
第一个是overwrite参数。它设置为true时,同一张表重复生成,XML映射文件会被覆盖;但Java类文件不会被覆盖。这是MBG的一个设计策略——XML由机器生成,覆盖无风险;而Java类你可能会手动改动,比如在实体类里额外加了字段或方法,所以默认不覆盖,避免你的手写代码被冲掉。如果想强制覆盖Java文件,需要在配置文件里单独配置<overwrite>相关参数,后面会讲到。
第二个是数据库驱动的引入位置。注意插件依赖和项目依赖是两回事,必须写在插件的<dependencies>里,否则插件运行时找不到JDBC驱动,会直接报ClassNotFoundException。这个坑我见过太多次了,驱动明明在项目依赖里有,插件就是加载不到。
3.2 核心配置文件逐段拆解(重点)
配置文件是整个MBG的核心。直接贴一份完整配置,然后逐段解释每个标签的作用。
<?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> <!-- 数据库驱动jar包路径(使用Maven插件时可省略) --> <classPathEntry location="/path/to/mysql-connector-java-8.0.28.jar"/> <context id="mysqlContext" targetRuntime="MyBatis3Simple" defaultModelType="flat"> <!-- 注释配置 --> <commentGenerator> <property name="suppressAllComments" value="true"/> </commentGenerator> <!-- 数据库连接信息 --> <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/test_db?useSSL=false&serverTimezone=Asia/Shanghai" userId="root" password="123456"/> <!-- 实体类生成配置 --> <javaModelGenerator targetPackage="com.example.demo.entity" targetProject="src/main/java"> <!-- 是否生成实体类的构造方法 --> <property name="constructorBased" value="false"/> <!-- 是否使用默认构造方法 --> <property name="immutable" value="false"/> <!-- 是否生成toString方法 --> <property name="toString" value="true"/> </javaModelGenerator> <!-- Mapper接口生成配置 --> <javaClientGenerator type="XMLMAPPER" targetPackage="com.example.demo.mapper" targetProject="src/main/java"/> <!-- 表生成配置 --> <table tableName="t_user" domainObjectName="User"> <property name="useActualColumnNames" value="false"/> <generatedKey column="id" sqlStatement="JDBC"/> </table> </context> </generatorConfiguration>逐个剖析。
classPathEntry:指定数据库驱动的jar包位置。用Maven插件方式时这个可以省略,因为插件<dependencies>里已经声明了驱动依赖。如果是命令行方式运行,这一项必填,否则无法加载驱动。
context:一个上下文代表一套连接配置和生成规则。注意targetRuntime有两个选项:MyBatis3和MyBatis3Simple。后者生成的是精简版代码,每个实体类只有基础的增删改查和按主键查询方法,代码体积小、可读性强,非常适合单表操作为主的项目。前者会额外生成大量的Example类(条件构造器),包揽了复杂条件查询,但生成代码明显膨胀。我建议大部分场景先用MyBatis3Simple,真的需要动态条件查询时,手动写一个方法加在XML里就够了,没必要让官方帮你生成一堆用不上的Example代码。
defaultModelType="flat":影响实体类的生成方式。flat模式是每个表对应一个实体类,所有字段平铺;hierarchical模式则会根据主键、BLOB字段等拆分成多个类,结构复杂但便于区分字段类型。默认用flat就够了,直观简洁。
commentGenerator:注释生成策略。默认情况下MBG会根据数据库表的注释信息生成实体类字段注释,但中文环境下经常出现乱码问题(后面第五章专门讲),而且生成的大段英文注释对团队开发没有实际帮助。suppressAllComments设为true后,生成代码里不会包含任何注释,代码完全由你掌控。有些团队喜欢保留注释,那就把它设为false,再配合<property name="addRemarkComments" value="true"/>来使用数据库表的注释信息,但前提是数据库连接参数里要指定useInformationSchema=true,否则注释信息仍然读不到。
javaModelGenerator:实体类生成的位置和规则。targetProject在Maven项目里可以直接写src/main/java,如果是多模块项目、生成目录不在当前模块下,需要写相对路径或绝对路径。几个property属性的含义:
constructorBased设为true会生成全参构造方法,默认不生成,适合需要创建完整对象的场景;immutable设为true会去掉setter方法,所有字段只能通过构造方法初始化,适合值对象模式,但日常开发不建议开;toString设为true会生成toString方法,方便调试打印,建议打开。
javaClientGenerator:Mapper接口生成配置。type="XMLMAPPER"表示生成XML映射文件+接口的方式,这是最标准的MyBatis用法。如果你喜欢注解方式,可以改成ANNOTATEDMAPPER,但注解方式只适合简单查询,复杂SQL还是要写XML,所以我始终建议用XMLMAPPER。
table:表与实体类的映射关系。tableName="t_user"明确指定要生成的表,domainObjectName="User"指定生成的实体类名(不写的话默认根据表名转驼峰命名)。useActualColumnNames设为false时,数据库字段user_name会自动转成userName;设为true则保留数据库原字段名。强烈建议保留false,否则Java代码里全是下划线命名,违反Java编码规范,看着非常别扭。
generatedKey:主键生成策略配置。column="id"告诉生成器哪个字段是自增主键,sqlStatement="JDBC"表示使用JDBC的getGeneratedKeys方法获取自增主键值。这个配置最终会反映在生成的插入语句里,自动带上useGeneratedKeys="true" keyProperty="id",插入后直接能从实体类里拿到自增id,非常实用。
3.3 运行生成命令与结果验证
配置完成后,在项目根目录执行命令:
mvn mybatis-generator:generate如果配置没问题,终端会打印出生成日志,显示每一张表生成的Java文件和XML文件路径。比如:
Generating class path entry... mybatis-generator:generate Table "t_user" generated successfully.生成后看一下目录结构,你应该能看到这些文件:
src/main/java/com/example/demo/ ├── entity/ │ └── User.java └── mapper/ └── UserMapper.java src/main/resources/ └── com/example/demo/mapper/ └── UserMapper.xml打开User.java,字段应该对应数据库表结构,id是Integer类型,createTime是LocalDateTime类型,这是1.4.0以上版本的重要变化。UserMapper.java接口里定义了insert、selectByPrimaryKey、selectAll、updateByPrimaryKey、deleteByPrimaryKey五个方法,UserMapper.xml里是这五个方法对应的SQL语句。
验证方式很简单,写一个测试类,注入UserMapper,调用insert方法插入一条数据,再调用selectByPrimaryKey查出来,能跑通就说明生成代码完全可用。
4. Java代码方式运行与定制化配置
4.1 编程方式快速实现
Maven插件的配置方式已经能满足大部分需求,但如果你想要更灵活的控制,比如根据不同的环境动态切换数据库,或者按表前缀批量生成,我建议用Java编程方式。
新建一个测试类,写一个main方法,调用MBG的ShellRunner或Configuration和MyBatisGenerator。最简单的做法是直接用ShellRunner加载配置文件:
import org.mybatis.generator.api.ShellRunner; public class GeneratorRunner { public static void main(String[] args) { // 第一个参数是配置文件路径,第二个参数是是否覆盖已存在的文件 String[] argsArr = {"-configfile", "src/main/resources/generatorConfig.xml", "-overwrite"}; ShellRunner.main(argsArr); } }这个方式本质上是把命令行参数搬到Java代码里,原理和Maven插件没有区别,但优点是调试方便,IDEA里右键直接运行,不需要每次敲Maven命令。如果你的项目完全没有用Maven,只是普通的Java工程,这个方式也适用——前提是把MBG的jar包和数据库驱动jar包加到classpath里。
更灵活的用法是直接用API方式构建配置,完全脱离XML文件:
import org.mybatis.generator.api.MyBatisGenerator; import org.mybatis.generator.config.*; import org.mybatis.generator.internal.DefaultShellCallback; import java.io.File; import java.util.ArrayList; import java.util.List; public class GeneratorWithCode { public static void main(String[] args) throws Exception { List<String> warnings = new ArrayList<>(); boolean overwrite = true; File configFile = new File("src/main/resources/generatorConfig.xml"); Configuration config = new ConfigurationParser(warnings).parseConfiguration(configFile); DefaultShellCallback callback = new DefaultShellCallback(overwrite); MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings); myBatisGenerator.generate(null); for (String warning : warnings) { System.out.println("警告: " + warning); } } }这个方式通过ConfigurationParser读取XML解析为配置对象,再交给MyBatisGenerator执行。好处是在执行前后可以任意写业务逻辑,比如生成完成后自动把实体类复制到另一个模块、或者在生成前动态修改配置对象。
4.2 多表批量生成的配置技巧
实际项目中很少只生成一张表,更多场景是生成整个数据库或指定前缀的多张表。在table标签里做点手脚就能实现。
tableName支持SQL通配符%,比如tableName="t_%"会匹配所有以t_开头的表。但要注意,如果tableName用了通配符,domainObjectName就不能写死,否则多张表会生成同一个类名,直接报错。这时不写domainObjectName,MBG会自动根据表名转换类名,比如t_user生成User,t_order生成Order。
还有一种需求是只需要某几张表。可以配置多个table标签,或者用<table tableName="user|order|product">这样的竖线分隔写法(仅当enableInsert之类的属性不需要个性化配置时可行)。
我实际用得最多的一个配置组合是:
<table tableName="t_%" > <property name="useActualColumnNames" value="false"/> <generatedKey column="id" sqlStatement="JDBC"/> </table>一条配置生成所有业务表,所有表统一使用id作为自增主键——这是比较标准的表设计约定。如果你的表设计里有联合主键或者不使用自增主键,需要针对这些特殊表单独再加一个table标签覆盖默认配置。
4.3 配置文件里的几个容易忽略的参数
有很多参数不太起眼,但实际影响很大,我整理几个高频使用的。
<javaTypeResolver>:类型解析器。默认会把数据库的decimal类型映射为BigDecimal,这是安全的选择。如果业务上明确知道某个字段不会出现小数,可以配置forceBigDecimals为false,让decimal映射为Double或Float,减少类型转换的麻烦。不过稳妥起见,涉及金额的字段还是建议保持BigDecimal。
<table>标签内的enableInsert、enableUpdateByPrimaryKey、enableDeleteByPrimaryKey、enableSelectByPrimaryKey等属性,分别控制是否生成对应的方法。如果你只需要查询功能,可以把enableInsert设为false,生成的Mapper方法列表会干净很多。
<sqlMapGenerator>:指定XML文件的生成目录。这个标签经常被人漏掉。如果<javaClientGenerator>配了XMLMAPPER但没配<sqlMapGenerator>,MBG会报错——它不知道XML该放哪。配置方式如下:
<sqlMapGenerator targetPackage="mapper" targetProject="src/main/resources"> </sqlMapGenerator>注意targetPackage的写法。如果这里写com.example.mapper,XML文件会生成在src/main/resources/com/example/mapper/目录。但实际项目里XML通常直接放在resources/mapper/下,所以targetPackage直接写mapper就行。
5. 生成结果解读与常见问题排查
5.1 生成代码的结构分析与改造建议
拿到生成的代码之后,不要急着直接往项目里塞,先花几分钟理解每一部分。
User.java实体类非常简单,就是数据库字段的Java映射,没有任何业务逻辑。需要注意的是,MBG生成的实体类没有实现序列化接口,如果想缓存实体到Redis或做分布式传输,需要自己加上implements Serializable。这也是我每次生成完必做的第一步改造。
UserMapper.java接口是空壳子,只有方法声明。MBG的核心逻辑全部在XML里。
UserMapper.xml是重点。打开看一下,resultMap定义了字段映射关系,Base_Column_List定义了查询时默认查询的字段列表,五个SQL语句分别是增删改查。你可以看到insert语句里用了useGeneratedKeys和keyProperty,这正是前面generatedKey配置生效的结果。
这里说一个很多人都会忽略的问题:生成的updateByPrimaryKey是一个全字段更新操作——哪个字段不为空就更哪个字段。这个行为适合明确知道要更新哪些字段的场景,但也意味着如果你只更新一个字段,其他字段会被置为NULL。实际开发中我通常会根据业务需求手写一个updateByPrimaryKeySelective方法,只更新非空字段。生成的代码是起点,不是终点,按需改造是正常流程。
5.2 注释乱码问题——高概率踩坑
生成代码里的中文注释出现乱码,是我见过最多的问题。现象是生成的实体类里字段注释显示成一堆???或乱码。
原因有两层。第一层是数据库连接URL里没有指定字符编码。MySQL 8默认连接字符集是utf8mb4,如果连接URL里没显式指定,中文注释经过JDBC传输可能丢失。解决办法是在connectionURL里加上:
jdbc:mysql://localhost:3306/test_db?useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf8注意XML文件里&符号要转义为&,所以实际配置里是这样的:
<jdbcConnection driverClass="com.mysql.cj.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/test_db?useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf8" userId="root" password="123456"/>第二层是MBG读取表注释信息需要显式开启。在<jdbcConnection>下加一个属性:
<property name="useInformationSchema" value="true"/>这样MBG才会通过JDBC的DatabaseMetaData接口获取表和字段的注释信息,否则它默认用可选的Remark信息,经常拿不到中文注释。两个配置都加上之后,中文注释基本就能正常生成了。
5.3 Example类的取舍策略
如果你用的是MyBatis3而不是MyBatis3Simple,生成的代码里会多出一个UserExample.java。这个类是为复杂查询设计的,支持where条件动态拼接、排序、分页等功能。
我的态度是:能用Simple模式就不用Example。原因有几个。一是Example代码生成后非常臃肿,一个简单的表可能生成一千多行代码,维护起来心里发慌;二是Example的使用方式比较绕,要创建Criteria、拼条件,代码可读性差,新接手的人需要额外学习;三是真正复杂的动态查询场景,手写XML反而更清晰可控。
如果项目遗留代码已经用了Example模式,也不需要急着重构。Example类本质上就是在Java里构造SQL的where条件,熟练之后也不算难用。它最适用的场景是管理后台的列表筛选——条件多、字段动态、组合复杂,用Example能省不少事。
5.4 生成代码与Lombok的整合方案
现在很多项目用Lombok简化实体类的getter/setter,但MBG默认生成的是完整的getter和setter方法。整合方式有两种。
第一种是生成后再手动删除getter/setter,在实体类上加上@Data注解。每次重新生成都要重复这个操作,比较繁琐。
第二种更优雅:通过配置让MBG直接不生成getter/setter方法。在<javaModelGenerator>里加两个属性:
<javaModelGenerator targetPackage="com.example.demo.entity" targetProject="src/main/java"> <!-- 不生成getter方法 --> <property name="generateGetter" value="false"/> <!-- 不生成setter方法 --> <property name="generateSetter" value="false"/> </javaModelGenerator>然后自己在实体类上手动加@Data注解。这样生成结果非常干净,实体类只保留字段定义和注解,配合Lombok使用。
5.5 常见问题排查速查表
把实际使用中频率最高的问题整理成一张表,方便参考。
| 问题现象 | 可能原因 | 解决方式 |
|---|---|---|
运行时报ClassNotFoundException: com.mysql.cj.jdbc.Driver | 插件没有引入数据库驱动 | 在Maven插件的<dependencies>里加入mysql-connector-java |
| 生成的实体类没有注释 | 未开启注释读取 | 在<jdbcConnection>里加<property name="useInformationSchema" value="true"/> |
| 注释显示乱码 | 连接URL未指定字符集 | 在connectionURL里加characterEncoding=utf8 |
| XML文件总是被覆盖 | 默认配置导致 | XML文件由MBG管理,覆盖属正常行为;Java文件不覆盖 |
| 生成Java文件不覆盖 | 默认安全策略 | 这是设计行为,如需覆盖需额外配置 |
LocalDateTime生成成了Date | 使用旧版本MBG | 升级到1.4.0以上版本 |
| 生成XML文件时找不到目录 | 未配置<sqlMapGenerator> | 添加该标签并指定targetPackage和targetProject |
| 重复生成时接口里的手写方法丢失 | Java文件不可覆盖 | 手写方法建议写到独立的类或写在XML中公用 |
| 生成的方法太少,没有条件查询 | 使用了MyBatis3Simple | 切换targetRuntime为MyBatis3,生成Example类 |
| 插入后无法获取自增主键 | 未配置generatedKey | 在<table>里加<generatedKey column="id" sqlStatement="JDBC"/> |
这些都是我实际遇到过并且解决过的问题,照着排查基本能覆盖95%的异常场景。
6. 从生成到落地:项目集成的几个要点
6.1 生成代码在Spring Boot中的衔接
生成代码如何接入Spring Boot项目,是很多人最后卡住的一步。MBG只负责生成文件,不负责管理Bean生命周期,所以要让Maper接口能被Spring管理,还需要做两件事。
第一件是在启动类上扫描Mapper接口。在Spring Boot启动类上加:
@MapperScan("com.example.demo.mapper") @SpringBootApplication public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }@MapperScan会扫描指定包下的所有Mapper接口,为它们生成代理实现类并注册为Spring Bean。如果没有这个注解,运行时会报No qualifying bean of type 'UserMapper'错误。
第二件是确保XML文件能被MyBatis加载。在application.yml里配置:
mybatis: mapper-locations: classpath:mapper/*.xml type-aliases-package: com.example.demo.entitymapper-locations指定XML映射文件的路径,type-aliases-package指定实体类所在包,这样XML里写resultType="User"时可以省略全限定类名,代码更清爽。
这两个配置配好之后,在Service层注入Mapper接口,直接调用方法即可。
6.2 增量生成的策略设计
项目维护阶段,表结构经常变动——加一个字段、改一个字段类型,这时候需要重新生成代码。MBG支持增量生成,但需要设计好策略。
我的做法是:实体类允许覆盖(字段变了,实体类里的属性必须同步),Mapper接口手写的方法保留(不覆盖),XML文件允许覆盖但手写的自定义SQL会丢。所以手写的自定义SQL尽量不要放在MBG生成的XML里,要么单独建一个XML文件,要么在Mapper接口里用注解。
具体操作上,重新生成前把Mapper接口里手写的方法先复制出来,生成完再贴回去。为了避免这个麻烦,我一般把手写的扩展方法放在单独的接口里,比如UserMapperExt.java,继承MBG生成的基础接口:
public interface UserMapperExt extends UserMapper { // 手写扩展方法 List<User> selectByAgeRange(Integer minAge, Integer maxAge); }这样即使每次重新生成UserMapper,扩展接口都不会受影响。这是一个很实用的架构思路,建议一早就规划好。
6.3 多数据源场景的注意事项
多数据源项目使用MBG时有几个特殊点。一个context只能配置一个数据源,所以多数据源时要配置多个context,每个context里分别指定不同的jdbcConnection和targetPackage。不过如果两张表在不同数据库但实体类想放同一个包,只要两个context的targetPackage一致就行。
还有一点,不同数据库驱动类不一样。比如Oracle用的是oracle.jdbc.driver.OracleDriver,连接URL格式也和MySQL不同。多数据源场景下,每个context的jdbcConnection里的driverClass、connectionURL、userId、password都要单独配置,不能共用。
7. 一些写在最后的经验
MBG用熟了之后,我最大的感受是:它帮你省掉的不是写代码的时间,而是切换上下文的精神损耗。写CRUD本来不需要动脑,但又不得不写,这种状态最消耗耐心。让工具干这种事,人才有精力去思考真正复杂的业务。
最后一个建议:拿到生成代码之后,花点时间通读一遍XML文件。MBG生成的SQL写法非常标准,尤其是ResultMap的字段映射、主键回填、批量操作的写法,多看几遍,你手写SQL的质量也会提高。很多团队允许新人用MBG生成入门代码,本质上是让新人先学会“正确的写法长什么样”,再逐步脱离工具手写。这也是我觉得这个工具对新手最有价值的地方。
根据我个人经验,第一次配置MBG时不要追求一步到位,先用最简单的单表配置跑通流程,再逐步添加表、调整参数。环境越简单,排错越容易,等你理解了每个参数的意义,再上复杂配置就完全不慌了。