【Uni-App+SSM+MP 宠物实战】Day6:MP 实体类与 Mapper 生成(附 MP 注解讲解)
一、前言
大家好!继续我们的 "mypet 宠物服务平台" 实战系列。今天我们深入 MyBatis-Plus(简称 MP)的核心功能 ------代码逆向生成。
MP 就像一个 "数据库助手",能自动将数据库表转换成 Java 代码(实体类、Mapper 接口),不用你从零手写重复的 SQL 语句和实体类字段。哪怕你是第一次接触 MP 也不用慌,我们会像搭积木一样,从配置到生成再到测试,一步步拆解操作。
今天的核心焦点是宠物信息模块( chongwuxinxi 表) ,通过 MP 生成该表对应的实体类和 Mapper 接口,帮你快速打通 "Java 代码操作数据库" 的链路,为后续开发宠物列表查询、新增宠物等功能打基础。
二、今日教学目标
- 理解 MP 逆向工程的作用(自动生成实体类、Mapper 接口,减少手写代码);
- 掌握 MP 代码生成器的配置步骤(指定输出路径、包名、目标表);
- 学会使用 MP 核心注解(@TableName、@TableId),理解其与数据库表的映射关系;
- 能通过生成的 Mapper 接口测试简单查询(如根据 ID 查询宠物信息)。
三、前置准备
- 已完成 Day5 数据库设计:chongwuxinxi(宠物信息表)已创建,且表中存在测试数据(如 ID=1 的宠物记录);
- 配置 MP 代码生成器依赖:打开项目 pom.xml(路径:C:\Users\骆\Downloads\my-pet-custom\mypet\pom.xml),确认已添加以下依赖(若缺失,需手动添加并执行 Maven Reload):
xml
<!-- MyBatis-Plus 代码生成器依赖 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.4.1</version>
</dependency>
<!-- 代码生成器需要的模板引擎(MP 默认依赖) -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.3</version>
</dependency>
(解释:mybatis-plus-generator 是核心生成工具,velocity-engine-core 用于解析生成模板,两者缺一不可);
- IDEA 环境正常:能正常打开项目,且 src/test/java 目录已存在(用于存放生成器测试类);
- 确认 MySQL 服务已启动:避免生成代码时因数据库连接失败报错。
四、代码实现(核心:MP 逆向生成步骤)
我们以 chongwuxinxi(宠物信息表)为例,分 3 步完成 "生成器配置 → 代码生成 → 注解补充":
1. 步骤 1:创建 MP 代码生成器测试类(GeneratorTest.java)
首先在 src/test/java 下新建测试类,通过配置指定生成规则(如输出路径、包名、目标表):
(1)新建测试类
- 在 IDEA 左侧 "Project" 面板,展开 src/test/java → 右键 java 目录 → New → Java Class;
- 类名输入 GeneratorTest → 选择 "Class" → 点击 "OK"。
(2)编写生成器配置代码
复制以下代码到 GeneratorTest.java,关键配置已加注释(需修改 outputDir 路径为你的项目路径):
arduino
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
public class GeneratorTest {
public static void main(String[] args) {
// 1. 创建 MP 自动生成器对象(核心"生成按钮")
AutoGenerator mpg = new AutoGenerator();
// 2. 配置全局参数(生成文件的通用规则)
GlobalConfig gc = new GlobalConfig();
// !!关键:设置代码输出路径(必须是你的项目 src/main/java 路径)
gc.setOutputDir("C:\Users\骆\Downloads\my-pet-custom\mypet\src\main\java");
gc.setAuthor("你的名字"); // 生成代码的作者(会显示在类注释中)
gc.setOpen(false); // 生成后不自动打开文件夹(避免弹窗干扰)
gc.setFileOverride(false); // 不覆盖已存在的文件(防止误删手动修改的代码)
// 设置生成的 Mapper 接口名后缀(默认是 Mapper,可自定义)
gc.setMapperName("%sMapper");
// 设置生成的实体类名后缀(默认无,这里加 Entity 区分,如 ChongwuxinxiEntity)
gc.setEntityName("%sEntity");
mpg.setGlobalConfig(gc);
// 3. 配置数据源(告诉 MP 连接哪个数据库)
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://localhost:3306/mypet?useUnicode=true&characterEncoding=utf8&useSSL=false");
dsc.setDriverName("com.mysql.jdbc.Driver"); // MySQL 5 驱动(MySQL 8 用 com.mysql.cj.jdbc.Driver)
dsc.setUsername("root"); // 数据库用户名(默认 root)
dsc.setPassword("123456"); // 数据库密码(Day1 设置的密码)
mpg.setDataSource(dsc);
// 4. 配置包结构(生成的代码放在哪个包下)
PackageConfig pc = new PackageConfig();
pc.setParent("com"); // 基础包名(所有生成的代码都在 com 包下)
pc.setEntity("entity"); // 实体类放在 com.entity 包
pc.setMapper("dao"); // Mapper 接口放在 com.dao 包
pc.setService("service"); // (可选)Service 层放在 com.service 包(今天暂不关注)
mpg.setPackageInfo(pc);
// 5. 配置策略(指定生成哪些表、字段命名规则)
StrategyConfig strategy = new StrategyConfig();
// !!关键:指定要生成的数据库表名(这里只生成 chongwuxinxi 表)
strategy.setInclude("chongwuxinxi");
// 数据库表名转实体类名的规则:下划线转驼峰(如 chongwuxinxi → ChongwuxinxiEntity)
strategy.setNaming(NamingStrategy.underline_to_camel);
// 数据库字段名转实体类属性名的规则:下划线转驼峰(如 pet_name → petName)
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
// 给实体类添加 Lombok 注解(可选,简化 getter/setter,今天暂不配置)
// strategy.setEntityLombokModel(true);
mpg.setStrategy(strategy);
// 6. 执行生成(按下"生成按钮")
mpg.execute();
System.out.println("代码生成完成!请查看 src/main/java/com 目录下的 entity 和 dao 包");
}
}
关键修改提醒:
- gc.setOutputDir:必须替换为你的项目 src/main/java 绝对路径(如 D:\my-pet\src\main\java),否则代码会生成到错误路径;
- 若使用 MySQL 8,需修改 dsc.setDriverName("com.mysql.cj.jdbc.Driver"),并在 dsc.setUrl 后加 &serverTimezone=UTC(如 jdbc:mysql://localhost:3306/mypet?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC)。
2. 步骤 2:运行生成器,生成实体类和 Mapper
- 在 GeneratorTest.java 中,右键 main 方法 → 选择 Run 'GeneratorTest.main()' ;
- 查看控制台输出,若显示类似以下内容,说明生成成功:
ini
[main] INFO com.baomidou.mybatisplus.generator.AutoGenerator - ========================== Starting Generator ==========================
[main] INFO com.baomidou.mybatisplus.generator.engine.VelocityTemplateEngine - Created: C:\Users\骆\Downloads\my-pet-custom\mypet\src\main\java\com\entity\ChongwuxinxiEntity.java
[main] INFO com.baomidou.mybatisplus.generator.engine.VelocityTemplateEngine - Created: C:\Users\骆\Downloads\my-pet-custom\mypet\src\main\java\com\dao\ChongwuxinxiMapper.java
[main] INFO com.baomidou.mybatisplus.generator.AutoGenerator - ========================== Generator Finished ==========================
代码生成完成!请查看 src/main/java/com 目录下的 entity 和 dao 包
- 验证生成的文件:
-
- 实体类:src/main/java/com/entity/ChongwuxinxiEntity.java(对应 chongwuxinxi 表的字段);
-
- Mapper 接口:src/main/java/com/dao/ChongwuxinxiMapper.java(继承 MP 的 BaseMapper,自带 CRUD 方法)。
3. 步骤 3:补充 MP 核心注解(映射数据库表)
生成的实体类默认已包含字段,但需手动添加 MP 注解,明确 "类与表、字段与列" 的映射关系(避免字段名与表列名不匹配的问题):
(1)打开生成的 ChongwuxinxiEntity.java
路径:src/main/java/com/entity/ChongwuxinxiEntity.java
(2)添加 MP 注解
修改代码,添加 @TableName(类注解)和 @TableId(主键字段注解),示例如下:
typescript
package com.entity;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.util.Date;
/**
* 宠物信息表(对应数据库 chongwuxinxi 表)
* @TableName 注解:告诉 MP 这个 Java 类对应哪个数据库表
*/
@TableName("chongwuxinxi")
public class ChongwuxinxiEntity implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键 ID(对应数据库表的 id 列)
* @TableId 注解:标记这个字段是表的主键,MP 会自动用它做查询条件(如 selectById)
*/
@TableId
private Long id;
/**
* 宠物名称(对应数据库表的 mingcheng 列)
* 若字段名与列名一致(驼峰转下划线后),无需额外注解(如 mingcheng → mingcheng)
*/
private String mingcheng;
/**
* 宠物品种(对应数据库表的 pinzhong 列)
*/
private String pinzhong;
/**
* 宠物年龄(对应数据库表的 nianling 列)
*/
private Integer nianling;
/**
* 创建时间(对应数据库表的 create_time 列)
*/
private Date createTime;
// 生成器自动生成的 getter 和 setter 方法(省略,实际代码中存在)
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getMingcheng() { return mingcheng; }
public void setMingcheng(String mingcheng) { this.mingcheng = mingcheng; }
// 其他 getter/setter 方法...
}
注解作用解释:
- @TableName("chongwuxinxi"):解决 "类名与表名不一致" 问题(如类名 Pet 对应表名 chongwuxinxi),这里类名是 ChongwuxinxiEntity,表名是 chongwuxinxi,也建议添加该注解明确映射;
- @TableId:标记主键字段(必须加),MP 会识别该字段为表的主键,后续调用 selectById() 时自动用该字段作为查询条件。
4. 步骤 4:查看生成的 Mapper 接口(ChongwuxinxiMapper.java)
生成的 Mapper 接口默认继承 MP 的 BaseMapper,自带 17 个 CRUD 方法(无需手写任何代码),路径:src/main/java/com/dao/ChongwuxinxiMapper.java,代码如下:
java
package com.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.entity.ChongwuxinxiEntity;
import org.apache.ibatis.annotations.Mapper;
/**
* 宠物信息 Mapper 接口(继承 BaseMapper 后,自带 CRUD 方法)
* @Mapper 注解:告诉 MyBatis 这是 Mapper 接口,Spring 会自动扫描并创建实例
*/
@Mapper
public interface ChongwuxinxiMapper extends BaseMapper<ChongwuxinxiEntity> {
// 无需手写方法!BaseMapper 已提供:
// 1. selectById(Long id):根据 ID 查询宠物
// 2. selectList(null):查询所有宠物
// 3. insert(ChongwuxinxiEntity pet):新增宠物
// 4. updateById(ChongwuxinxiEntity pet):根据 ID 修改宠物
// 5. deleteById(Long id):根据 ID 删除宠物
// ... 其他方法
}
五、效果验证(测试 Mapper 查询功能)
我们通过 "根据 ID 查询宠物信息" 验证生成的代码是否可用,步骤如下:
1. 新建测试类(ChongwuxinxiTest.java)
- 在 src/test/java 下新建 com.test 包(若已存在则直接用);
- 在 com.test 包下新建 ChongwuxinxiTest.java。
2. 编写测试代码
kotlin
package com.test;
import com.dao.ChongwuxinxiMapper;
import com.entity.ChongwuxinxiEntity;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
// 加载 Spring 配置文件,确保能注入 Mapper 接口
@ContextConfiguration(locations = {"classpath:spring/spring-mybatis.xml"})
public class ChongwuxinxiTest {
// 自动注入 ChongwuxinxiMapper(Spring 会通过 MP 生成实现类)
@Autowired
private ChongwuxinxiMapper chongwuxinxiMapper;
@Test
public void testSelectById() {
// 假设数据库 chongwuxinxi 表中存在 ID=1 的宠物记录
Long petId = 1L;
// 调用 MP 自带的 selectById() 方法查询宠物
ChongwuxinxiEntity pet = chongwuxinxiMapper.selectById(petId);
// 打印查询结果到控制台
if (pet != null) {
System.out.println("查询到的宠物信息:");
System.out.println("宠物 ID:" + pet.getId());
System.out.println("宠物名称:" + pet.getMingcheng());
System.out.println("宠物品种:" + pet.getPinzhong());
System.out.println("宠物年龄:" + pet.getNianling() + " 岁");
} else {
System.out.println("未查询到 ID=" + petId + " 的宠物,请检查数据库数据!");
}
}
}
3. 运行测试方法
- 右键 testSelectById() 方法 → 选择 Run 'testSelectById()' ;
-
查看控制台输出,若显示类似以下内容,说明生成的代码正常工作:
查询到的宠物信息:
宠物 ID:1
宠物名称:小白
宠物品种:萨摩耶
宠物年龄:2 岁 -
若显示 "未查询到宠物",需先在 chongwuxinxi 表插入测试数据(参考 Day5 的插入语句):
sql
INSERT INTO chongwuxinxi (mingcheng, pinzhong, nianling)
VALUES ('小白', '萨摩耶', 2);
六、常见问题与解决方案
问题描述 | 可能原因 | 解决方案 |
---|---|---|
运行 GeneratorTest 时,控制台报 "Could not create connection to database server" | 1. MySQL 服务未启动;2. 数据库连接参数错误(如 URL、密码) | 1. 按 Win+R 输入 services.msc,启动 "MySQL" 服务;2. 检查 DataSourceConfig 中:URL 是否正确(数据库名是 mypet)、密码是否为 Day1 设置的 123456、驱动类是否匹配 MySQL 版本 |
生成的代码找不到(控制台显示生成成功,但 src/main/java 下无文件) | gc.setOutputDir 路径错误(如写成 C:\test\src\main\java,非项目路径) | 1. 打开 GeneratorTest.java,检查 gc.setOutputDir 的值;2. 替换为项目实际的 src/main/java 路径(可在 IDEA 中右键 src/main/java → 选择 "Copy Path" 获取绝对路径) |
测试时报 "org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.dao.ChongwuxinxiMapper' available" | 1. Mapper 接口未加 @Mapper 注解;2. Spring 未扫描到 Mapper 包 | 1. 检查 ChongwuxinxiMapper.java 是否有 @Mapper 注解(生成器默认已添加);2. 检查 spring-mybatis.xml 中是否配置 <mybatis:scan base-package="com.dao"/>(扫描 Mapper 包) |
实体类中 @TableName 注解报 "Cannot resolve symbol 'TableName'" | MP 注解依赖未导入,或 IDEA 未识别依赖 | 1. 检查 pom.xml 中是否有 MP 核心依赖(mybatis-plus);2. 在实体类中手动导入注解:import com.baomidou.mybatisplus.annotation.TableName;;3. 右键项目 → Maven → Reload Project 刷新依赖 |
七、工具类 / 框架特性拓展
MP BaseMapper vs 原生 MyBatis:代码量对比
功能需求 | 原生 MyBatis 实现步骤 | MP BaseMapper 实现步骤 | 效率差异 |
---|---|---|---|
根据 ID 查询宠物 | 1. 在 Mapper 接口写 ChongwuxinxiEntity selectById(Long id);;2. 在 Mapper XML 写 SELECT * FROM chongwuxinxi WHERE id=#{id} | 1. Mapper 接口继承 BaseMapper;2. 直接调用 chongwuxinxiMapper.selectById(1L) | 无需写 XML,代码量减少 90% |
查询所有宠物 | 1. 写 List selectAll();;2. XML 写 SELECT * FROM chongwuxinxi | 直接调用 chongwuxinxiMapper.selectList(null) | 一步到位,无需任何手写代码 |
后续开发 orders(订单表)、shangjia(商家表)时,可直接复用今天的 GeneratorTest 代码,只需修改 strategy.setInclude("orders") 即可快速生成对应代码,大幅节省开发时间。
八、结语
今天第一次用 MP 生成代码,你是否成功在 com.entity 和 com.dao 包下看到生成的文件?测试 selectById() 时是否查询到了宠物信息?
如果遇到 "数据库连接失败""生成的代码找不到" 等问题,欢迎在评论区贴出你的控制台错误日志(关键部分即可),我们一起一步步排查;如果成功生成并测试通过,也可以分享你的宠物查询结果,让大家一起感受 MP 简化开发的魅力!
小马绿泡泡:Niuma4G
下期预告
Day7:SpringMVC 接口测试(基于今天生成的 Mapper 接口,开发 "查询宠物列表" 的 SpringMVC 接口,通过 Postman 测试接口是否能返回数据,为前端 Uni-App 调用接口做准备)。