[toc]
| 单词 | 词性 | 音标 | 含义 |
|---|---|---|---|
| Generator | n. | /ˈdʒenəreɪtə(r)/ | 生成器(根据模板批量生成代码的程序) |
| Reverse Engineering | - | /rɪˈvɜːs ˌendʒɪˈnɪərɪŋ/ | 逆向工程(从数据库表结构反推出代码) |
| Template | n. | /ˈtemplət/ | 模板(生成代码所用的模板文件) |
| Plugin | n. | /ˈpluːɡɪn/ | 插件(IDEA 中增强功能的扩展组件) |
| Skeleton | n. | /ˈskelɪtn/ | 骨架(生成的基础代码,业务逻辑需自己补充) |
| Entity | n. | /ˈentəti/ | 实体类(与数据库表对应的类) |
Lecture13-MyBatisPlus逆向工程
Hibernate 正向过程:Java 实体类 --生成--> 数据库表
Mybatis/MybatisPlus 逆向工程:数据库表 --生成--> 一整套 Java 资源
- Java 实体类
- Mapper 接口文件
- Mapper.xml 配置文件
- XxxService 接口和实现类
一、什么是逆向工程(代码生成器)
回顾前 12 章:每新增一张表,我们都要手动创建实体类、Mapper 接口、Service、ServiceImpl、Controller……大量重复劳动。
「逆向工程」就是解决这个痛点:根据数据库表,自动生成一整套可运行的代码骨架。MyBatis-Plus 生态提供了两种主流做法:
| 做法 | 说明 | 适合谁 |
|---|---|---|
| 方式一:代码生成器(FastAutoGenerator) | 写一个 Java 配置类,运行 main 方法批量生成 | 团队统一模板、命令行/CI 环境 |
| 方式二:IDEA MyBatisX 插件 | IDEA 图形界面勾选,右键一键生成 | 个人日常开发、快速出代码 |
注意:两种方式生成的都是骨架,CRUD 方法开箱即用,但具体业务逻辑(比如"工资不能为负")需要自己补充。
二、方式一:代码生成器(FastAutoGenerator)
MyBatis-Plus 官方代码生成器,3.5.1 版本之后推荐使用 FastAutoGenerator(builder 模式,配置直观):
1、添加依赖
在 pom.xml 中追加两个依赖:
<!-- 代码生成器:版本与 mybatis-plus-spring-boot3-starter 保持一致 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.17</version>
</dependency>
<!-- 模板引擎:代码生成器依赖模板引擎,本教程使用 Freemarker -->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
</dependency>
两个要点:
- 代码生成器必须搭配一个模板引擎才能工作(Velocity 是默认,Freemarker/Beetl 等均可),不引入会直接报错
- 生成器只在开发期运行,不影响运行时的依赖大小
2、准备演示表
用一张前面课程没建过的新表演示,避免覆盖已有代码:
CREATE TABLE t_customer (
customer_id INT PRIMARY KEY AUTO_INCREMENT COMMENT '客户ID',
customer_name VARCHAR(50) NOT NULL COMMENT '客户姓名',
phone VARCHAR(20) COMMENT '手机号',
email VARCHAR(100) COMMENT '邮箱',
create_time DATETIME COMMENT '创建时间',
update_time DATETIME COMMENT '更新时间',
deleted TINYINT DEFAULT 0 COMMENT '逻辑删除标记'
) COMMENT '客户表';
INSERT INTO t_customer (customer_name, phone, email)
VALUES ('刘一', '13800000001', 'liuyi@atguigu.com'),
('陈二', '13800000002', 'chener@atguigu.com');
3、编写生成器类并运行
新建测试类 Generator(放在 src/test/java 或任意位置,直接运行 main 方法):
package com.atguigu.mp.generator;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import com.baomidou.mybatisplus.generator.fill.Column;
import java.util.Collections;
public class Generator {
public static void main(String[] args) {
// 数据源:与 application.properties 保持一致
FastAutoGenerator.create(
"jdbc:mysql://192.168.100.100/db_hr",
"atguigu", "atguigu")
// ① 全局配置
.globalConfig(builder -> builder
.author("atguigu") // 作者(写进注释)
.outputDir("D:/260525班授课资料/Part03-Java应用开发-[7day]03-Mybatis部分/src/main/java") // 源码输出目录
.disableOpenDir() // 生成后不自动打开目录
.fileOverride() // 已存在同名文件也覆盖
)
// ② 包配置:生成到哪个包
.packageConfig(builder -> builder
.parent("com.atguigu.mp") // 父包
.entity("entity") // 实体包
.mapper("mapper") // Mapper 包
.service("service") // Service 包
.serviceImpl("service.impl") // ServiceImpl 包
.controller("controller") // Controller 包
.pathInfo(Collections.singletonMap( // Mapper XML 输出到 resources
OutputFile.xml,
"D:/260525班授课资料/Part03-Java应用开发-[7day]03-Mybatis部分/src/main/resources/mapper"))
)
// ③ 策略配置:生成哪些表、怎么生成
.strategyConfig(builder -> builder
.addInclude("t_customer") // 要生成的表
.addTablePrefix("t_") // 生成实体时去掉表前缀 t_
.entityBuilder()
.enableLombok() // 生成 @Data 注解
.enableTableFieldAnnotation() // 每个字段加 @TableField
.idType(IdType.AUTO) // 主键策略:自增
.logicDeleteColumnName("deleted") // 逻辑删除字段
.addTableFills( // 自动填充字段
new Column("create_time", FieldFill.INSERT),
new Column("update_time", FieldFill.INSERT_UPDATE))
.controllerBuilder()
.enableRestStyle() // Controller 用 @RestController
)
// ④ 模板引擎(与 pom 中引入的 Freemarker 对应)
.templateEngine(new FreemarkerTemplateEngine())
// ⑤ 执行生成
.execute();
}
}
提示:
outputDir要改成你自己工程的实际路径。课程工程若没有src/main/java目录,IDEA 会自动创建。
运行 main 方法,控制台输出类似(不同版本日志略有差异):
2026-09-23 16:40:12.123 INFO 3456 --- [ main] c.a.m.generator.Generator : ========== 开始生成代码 ==========
2026-09-23 16:40:12.456 INFO 3456 --- [ main] c.a.m.generator.Generator : 已生成: entity/Customer.java
2026-09-23 16:40:12.468 INFO 3456 --- [ main] c.a.m.generator.Generator : 已生成: mapper/CustomerMapper.java
2026-09-23 16:40:12.480 INFO 3456 --- [ main] c.a.m.generator.Generator : 已生成: mapper/CustomerMapper.xml
2026-09-23 16:40:12.492 INFO 3456 --- [ main] c.a.m.generator.Generator : 已生成: service/CustomerService.java
2026-09-23 16:40:12.505 INFO 3456 --- [ main] c.a.m.generator.Generator : 已生成: service/impl/CustomerServiceImpl.java
2026-09-23 16:40:12.518 INFO 3456 --- [ main] c.a.m.generator.Generator : 已生成: controller/CustomerController.java
2026-09-23 16:40:12.520 INFO 3456 --- [ main] c.a.m.generator.Generator : ========== 代码生成完成 ==========
4、查看生成的代码
生成的文件结构:
src/main/java/com/atguigu/mp/
├── entity/Customer.java
├── mapper/CustomerMapper.java
├── service/CustomerService.java
├── service/impl/CustomerServiceImpl.java
└── controller/CustomerController.java
src/main/resources/mapper/
└── CustomerMapper.xml
(1)实体类 Customer(关键部分)
package com.atguigu.mp.entity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.time.LocalDateTime;
@Data
@TableName("t_customer") // 表名:去掉 t_ 前缀
public class Customer {
@TableId(type = IdType.AUTO)
private Integer customerId;
@TableField("customer_name")
private String customerName;
private String phone;
private String email;
@TableField(fill = FieldFill.INSERT) // 自动填充:插入时填
private LocalDateTime createTime;
@TableField(fill = FieldFill.INSERT_UPDATE) // 自动填充:插入/更新时填
private LocalDateTime updateTime;
@TableLogic // 逻辑删除
private Integer deleted;
}
(2)Mapper、Service、Controller
@Mapper
public interface CustomerMapper extends BaseMapper<Customer> {
}
public interface CustomerService extends IService<Customer> {
}
@Service
public class CustomerServiceImpl extends ServiceImpl<CustomerMapper, Customer>
implements CustomerService {
}
@RestController
@RequestMapping("/customer")
public class CustomerController {
@Autowired
private CustomerService customerService;
}
对照前几章可以发现:生成的代码和我们手写的完全一样——@TableName、@TableId、@TableField、@TableLogic、IService/ServiceImpl 这些注解和基类全部自动配好,直接可用。
三、方式二:IDEA MyBatisX 插件(勾选式逆向工程)
除了写代码运行生成器,MyBatis-Plus 官方还提供了 IDEA 插件 MyBatisX:不写一行代码,在 IDEA 里点点鼠标就能完成逆向工程。
1、安装插件
- File → Settings → Plugins → Marketplace
- 搜索
MyBatisX→ Install - 安装完成后重启 IDEA(插件为 MyBatis-Plus 官方出品)
2、连接数据库
- 打开 IDEA 右侧
Database面板 → + → Data Source → MySQL - 填写:Host
192.168.100.100、Useratguigu、Passwordatguigu、Databasedb_hr - 点击 Test Connection 测试连接(第一次会提示下载驱动,按提示下载即可)→ OK
3、右键表,勾选配置,一键生成
(1)展开 db_hr → Tables,右键 t_customer → 选择 MybatisX-Generator
(2)弹出的配置窗口第一页:
| 选项 | 填写/勾选 | 说明 |
|---|---|---|
| Module path | 选择当前模块 | 代码生成到哪个工程模块 |
| base package | com.atguigu.mp | 基础包名 |
| relative package | entity | 实体类所在的相对包 |
| Comment | 勾选 | 把表/字段注释生成到代码 |
| Lombok | 勾选 | 实体类使用 @Data |
| 其余选项 | 默认 | 类名、忽略字段等按需调整 |
(3)点击 Next 进入模板配置页:
- 模板选择:Mybatis-Plus 3
- 勾选 Lombok
- 确认要生成的层级:Entity / Mapper / Service / Controller(Mapper XML 默认生成到
src/main/resources/mapper)
(4)点击 Finish,生成完毕。
提示:可以一次选中多张表一起生成。
4、查看生成的代码
产物与方式一基本一致:
src/main/java/com/atguigu/mp/
├── entity/Customer.java
├── mapper/CustomerMapper.java
├── service/CustomerService.java
├── service/impl/CustomerServiceImpl.java
└── controller/CustomerController.java
src/main/resources/mapper/
└── CustomerMapper.xml
实体同样是 @TableName、@TableId、@TableField、Lombok 齐全,是否带 @TableLogic、自动填充取决于库表字段和勾选情况,生成后直接可运行。
5、MyBatisX 的其它实用小功能
- Mapper 接口 ↔ Mapper XML 方法之间的互相跳转(方法名旁的小箭头)
- Mapper 方法一键生成 SQL 片段
- 后续学习 MyBatis 的 XML 写法时非常好用(本教程不展开)
四、两种方式如何选择
| 对比项 | 方式一:FastAutoGenerator | 方式二:MyBatisX 插件 |
|---|---|---|
| 额外依赖 | 需要 generator + 模板引擎 | 不需要,装插件即可 |
| 操作方式 | 写 Java 配置类,运行 main | IDEA 图形界面勾选 |
| 可复用性 | 配置类可长期保存、一键批量生成 | 每次右键操作,所见即所得 |
| 适合场景 | 团队统一模板 / CI 环境 | 个人日常开发 |
| 生成产物 | entity / mapper+XML / service / controller | 与方式一基本一致 |
一般原则:个人开发用插件,团队项目用代码生成器(模板统一、可提交到版本库)。
五、测试生成的代码
两种方式生成的代码产物一致,下面的测试对两种方式都适用。注入生成的 CustomerMapper 使用:
@SpringBootTest
public class CustomerTest {
@Autowired
private CustomerMapper customerMapper;
@Test
public void testInsertAndSelect() {
// 新增:自动填充 createTime,自动维护逻辑删除字段
Customer customer = new Customer();
customer.setCustomerName("王五");
customer.setPhone("13800000003");
customerMapper.insert(customer);
// 查询全部(自动过滤 deleted=0)
List<Customer> list = customerMapper.selectList(null);
list.forEach(c -> System.out.println(
c.getCustomerId() + " - " + c.getCustomerName() + " - " + c.getCreateTime()));
}
}
==> Preparing: INSERT INTO t_customer ( customer_name, phone, create_time, update_time, deleted ) VALUES ( ?, ?, ?, ?, ? )
==> Parameters: 王五(String), 13800000003(String), 2026-09-23T16:40:30(String), 2026-09-23T16:40:30(String), 0(Integer)
==> Preparing: SELECT customer_id,customer_name,phone,email,create_time,update_time,deleted FROM t_customer WHERE deleted=0
逻辑删除、自动填充这些前几章手写的配置,生成器全部帮你配好了。
六、注意事项
- 同名文件默认不覆盖、覆盖前先备份(两种方式通用):方式一需要
fileOverride()开启才覆盖;方式二生成时遇到同名文件会提示。课程的t_emp实体被手工定制过(@TableLogic、@Version、忽略字段等),若对它重新生成,定制内容会丢失——生成前先备份 - 生成器版本与 starter 版本保持一致:本教程统一 3.5.17
- 模板引擎必须引入:pom 中不加 freemarker/velocity 会直接报错(仅方式一需要)
- 生成的 Controller/Service 是空壳骨架:只保证能编译运行,业务校验、事务、复杂查询都要自己补
- 表注释、字段注释会自动生成到类/字段的 Javadoc 上(MySQL 连接串加
remarks=true&useInformationSchema=true可读注释,MySQL 8 驱动一般默认可读) - MyBatisX 插件使用 IDEA Database 面板的连接;工程运行时的数据源是
application.properties,两者相互独立——数据库地址变化时两处都要改
七、本章小结
- 逆向工程 = 根据数据库表自动生成代码骨架,解决重复劳动
- 方式一:FastAutoGenerator——加依赖(generator + 模板引擎)→ 写 Generator 配置类 → 运行 main
- 方式二:MyBatisX 插件——安装插件 → Database 连接数据库 → 右键表勾选配置 → Finish
- 关键配置回顾:
globalConfig/packageConfig/strategyConfig/templateEngine(方式一);Module path / base package / relative package / Comment / Lombok / Mybatis-Plus 3 模板(方式二) - 生成的是可运行骨架,业务逻辑在此基础上补充;覆盖前先备份