💡 一则也许对你有用的小广告 🏆
欢迎飞飞程序员 ,你将获得:专属的实战项目(已更新的所有会员标识的项目都能学习) / 1v1 提问 / Java 学习路线 / PHP 学习路线 / 学习打卡 / 社群讨论
截止目前, 飞飞 正在疯狂爆肝实战项目,后续还会上新更多项目,目标是将所学知识开发成项目并且分享给大家,如知识付费系统, Ai系统, CMS系统,在线商城系统,等等 ,欢迎点击围观
📚 Mapper 和 DO 的关系详解
1️⃣ DO (Data Object) - 数据对象
DO 是数据库表的 Java 映射对象,对应数据库中的一张表:
@TableName("t_article") // 对应数据库表 t_article
public class ArticleDO {
@TableId(type = IdType.AUTO)
private Long id; // 对应 id 字段
private String title; // 对应 title 字段
private String cover; // 对应 cover 字段
private LocalDateTime createTime; // 对应 create_time 字段
// ...
}
作用:
- 📋 表结构映射:Java 类的字段对应数据库表的列
- 🔄 数据载体:在应用和数据库之间传输数据
- 📦 数据封装:将数据库记录封装成 Java 对象
2️⃣ Mapper - 数据访问接口
Mapper 是操作数据库的接口,定义了对某个表的增删改查方法:
// ArticleMapper 操作 ArticleDO(即 t_article 表)
public interface ArticleMapper extends BaseMapper<ArticleDO> {
// 继承 BaseMapper 后自动拥有 CRUD 方法
// 可以添加自定义查询方法
default Page<ArticleDO> selectPageList(...) {
// 分页查询文章
}
default Integer selectAvgReadNum() {
// 计算平均阅读数
}
}
作用:
- 🔧 数据库操作:执行 SQL 增删改查
- 📝 SQL 生成:通过 MyBatis-Plus 自动生成 SQL
- 🎯 业务方法:封装复杂的查询逻辑
3️⃣ Mapper 和 DO 的关系
┌─────────────────────────────────────────────┐
│ Service 层 │
│ (业务逻辑,调用 Mapper 操作数据) │
└─────────────────┬───────────────────────────┘
│
↓
┌─────────────────────────────────────────────┐
│ ArticleMapper │ ← Mapper 接口
│ extends BaseMapper<ArticleDO> │
│ │
│ - insert(ArticleDO) 插入一条记录 │
│ - deleteById(Long id) 删除 │
│ - updateById(ArticleDO) 更新 │
│ - selectById(Long id) 查询 │
│ - selectList(...) 列表查询 │
│ - selectPageList(...) 自定义分页查询 │
└─────────────────┬───────────────────────────┘
│ 泛型参数:指定操作哪个 DO
↓
┌─────────────────────────────────────────────┐
│ ArticleDO │ ← 数据对象
│ @TableName("t_article") │
│ │
│ - Long id │
│ - String title │
│ - String cover │
│ - LocalDateTime createTime │
└─────────────────┬───────────────────────────┘
│ 映射关系
↓
┌─────────────────────────────────────────────┐
│ 数据库表 t_article │
│ │
│ id (bigint) │
│ title (varchar) │
│ cover (varchar) │
│ create_time (datetime) │
└─────────────────────────────────────────────┘
4️⃣ 一对一关系
| Mapper | DO | 数据库表 |
ArticleMapper | ArticleDO | t_article |
WikiArticleMapper | WikiArticleDO | t_wiki_article |
CommentMapper | CommentDO | t_comment |
UserMapper | UserDO | t_user |
规律:
- 1 个 Mapper 对应 1 个 DO
- 1 个 DO 对应 1 张数据库表
- Mapper 通过泛型
BaseMapper<DO> 指定操作哪个表
5️⃣ 实际使用示例
场景:在 Service 中查询文章
@Service
public class AdminArticleServiceImpl {
@Autowired
private ArticleMapper articleMapper; // 注入 Mapper
public Response findArticleDetail(Long articleId) {
// 1. 使用 Mapper 查询数据库,返回 DO 对象
ArticleDO articleDO = articleMapper.selectById(articleId);
// 2. DO 转 VO(给前端的数据)
FindArticleDetailRspVO vo = convertDO2VO(articleDO);
return Response.success(vo);
}
}
执行流程:
Service 调用 → Mapper.selectById(1)
↓
生成 SQL: SELECT * FROM t_article WHERE id = 1
↓
执行查询,返回数据库记录
↓
MyBatis 自动封装成 ArticleDO 对象
↓
返回给 Service 使用
6️⃣ Mapper 提供的常用方法
继承 BaseMapper<T> 后自动拥有:
| 方法 | 说明 | SQL 示例 |
insert(DO) | 插入记录 | INSERT INTO t_article ... |
deleteById(id) | 按 ID 删除 | DELETE FROM t_article WHERE id = ? |
updateById(DO) | 按 ID 更新 | UPDATE INTO t_article SET ... WHERE id = ? |
selectById(id) | 按 ID 查询 | SELECT * FROM t_article WHERE id = ? |
selectList(wrapper) | 条件查询列表 | SELECT * FROM t_article WHERE ... |
selectPage(page, wrapper) | 分页查询 | SELECT * FROM t_article ... LIMIT ?, ? |
7️⃣ 为什么要分 Mapper 和 DO?
| 层次 | 职责 | 优势 |
| DO | 数据载体,只负责属性 | 清晰的数据结构,易于维护 |
| Mapper | 数据库操作,只负责 SQL | 分离关注点,便于测试和扩展 |
好处:
- ✅ 职责分离:DO 负责数据,Mapper 负责操作
- ✅ 可维护性:修改表结构只需改 DO,修改查询逻辑只需改 Mapper
- ✅ 可复用性:同一个 DO 可以在多个 Service 中使用
- ✅ 自动化:MyBatis-Plus 自动实现基础 CRUD,无需写 XML
8️⃣ 对比其他概念
| 概念 | 位置 | 作用 |
| DO | domain/dos | 数据库表映射 |
| Mapper | domain/mapper | 数据库操作接口 |
| VO | model/vo | 前后端数据交互 |
| Service | service | 业务逻辑处理 |
| Controller | controller | 接收请求,调用 Service |
🎯 总结
- DO (Data Object):数据库表的 Java 类表示
- Mapper:操作数据库的接口,通过泛型指定操作哪个 DO
- 关系:
Mapper<DO> → DO → 数据库表
- 作用链:
Controller → Service → Mapper → 数据库
形象比喻:
- DO 是一个快递包裹(装数据)
- Mapper 是快递员(运输数据)
- 数据库 是仓库(存储数据)
快递员(Mapper)负责把包裹(DO)送到仓库(数据库)或从仓库取出来!📦🚚