💡 一则也许对你有用的小广告 🏆

欢迎飞飞程序员   ,你将获得:专属的实战项目(已更新的所有会员标识的项目都能学习) / 1v1 提问 / Java 学习路线 / PHP 学习路线 / 学习打卡 / 社群讨论

  • 正在进行中的项目:《FFBlog知识付费博客项目》 正在持续更新中,基于 Spring Boot 3.x + JDK 21...,点击查看 ;
  • 《从零开发:FFBlog知识付费博客项目(全栈开发)》 演示链接: https://ffblog.ffcxy.com/  ;

截止目前, 飞飞  正在疯狂爆肝实战项目,后续还会上新更多项目,目标是将所学知识开发成项目并且分享给大家,如知识付费系统, 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 分离关注点,便于测试和扩展

好处

  1. 职责分离:DO 负责数据,Mapper 负责操作
  2. 可维护性:修改表结构只需改 DO,修改查询逻辑只需改 Mapper
  3. 可复用性:同一个 DO 可以在多个 Service 中使用
  4. 自动化: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数据库表
  • 作用链ControllerServiceMapper数据库

形象比喻

  • DO 是一个快递包裹(装数据)
  • Mapper快递员(运输数据)
  • 数据库仓库(存储数据)

快递员(Mapper)负责把包裹(DO)送到仓库(数据库)或从仓库取出来!📦🚚

上一篇 mvn clean compile -DskipTests用法详解
下一篇 通过实际代码来解释 Service 接口和ServiceImpl 实现类的关系

全部评论(0)

头像
😃 😁 😅 😂 😍 😜 😝 🤑 🥵 🥰 😙 😎 😵 😭 😱 😖 🥳 👽 🙈 🤡 😤 💣 💯 💢 ❤️ 👍 👏 👋 👌 🤏 🙏
还没有任何评论哟~