IService 和 BaseMapper:CRUD 操作的选择指南

大家有没有注意到这么一个情况在我们平常开发的时候,会遇到一个有趣的重复现象:Dao 层 继承的 BaseMapper 提供了一系列 CRUD 方法,而Service层 接口继承的 IService 也提供了一套看起来非常相似的 CRUD 操作。那么我们在开发的时候到底该用哪个?它们有什么区别吗?

一、角色定位(这大家都知道)

  1. BaseMapper:Dao 层的"工具箱" 它属于 数据访问层(DAO/Mapper) 。这个是直接和数据库打交道的。它的方法直接对应着 一个SQL 语句。不关心业务逻辑,只负责把数据存进去或按条件查出来。

  2. IService: 它属于 业务逻辑层(Service) 。这是处理业务规则 在 BaseMapper 提供的"原子工具"基础上,构建更符合业务场景 的操作。它可能包含组合操作、批量操作、业务校验等。 方法往往更偏向于业务逻辑处理,例如 saveOrUpdate(保存或更新)、saveBatch(批量保存)、listByIds(按ID集合批量查询)、page(带分页的查询)。它是事务的边界,比如事务回滚啥的。

二、主要的区别

特性 BaseMapper (Dao层) **IService (Service层) **
定位 数据访问 (直接操作访问数据库) 主要处理业务逻辑
操作粒度 原子操作 (单条记录/简单条件) 业务操作 (可能组合多个原子操作,批量操作)
事务性 Dao层一般牵扯不到事务 有事务,比如@Transactional事务回滚等
业务逻辑 按理说这里没有业务逻辑 主要业务逻辑的处理,校验唯一性,数据是否存在,List数据组合等等
复杂度 (直接映射SQL) 相对较高 (封装组合逻辑)

三、实战演示:代码里的"双胞胎"

1. Dao 层 (使用 BaseMapper)

java 复制代码
// UserDao.java (Mapper 接口)
public interface UserDao extends BaseMapper<User> {
    // 通常只需要继承 BaseMapper,基础CRUD方法就有了
    // 可以在这里定义额外的、复杂SQL的自定义方法
}

2. Service 层接口 (使用 IService)

java 复制代码
// UserService.java (Service 接口)
public interface UserService extends IService<User> {
    // 继承了 IService 的通用CRUD方法
    // 可以在这里定义业务相关的特定方法
}

3. Service 层实现 (依赖 BaseMapper 实现 IService)

java 复制代码
// UserServiceImpl.java (Service 实现类)
@Service
public class UserServiceImpl extends ServiceImpl<UserDao, User> implements UserService {
    // 关键点在这里:ServiceImpl 内部已经注入了 UserDao (即 BaseMapper<User>)
    // 它利用 UserDao 提供的基础能力来实现 IService 接口中定义的更高级方法
    // 例如:
    //   @Override
    //   @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    //   public boolean saveBatch(Collection<User> entityList) {
    //       // 这里可能会使用循环 + userDao.insert(entity) 或更优的批量策略
    //       // 并且这个方法默认在一个事务内执行!
    //   }
}

关键观察:

  • UserDao是真正执行 SQL 的底层工具。
  • UserServiceImpl 实现了 IService 接口。
  • UserServiceImpl 内部依赖 UserDao来完成其功能。IService 的方法本质上是构建在 BaseMapper基础之上的。
  • IService 的 saveBatch等方法内部会调用 BaseMapperinsert 方法(可能多次或使用批处理),并在这个过程上加上了事务管理。

四、如何进行选择

明白了区别,选择就清晰多了:

  1. 在 Service 实现类 (ServiceImpl) 内部:

    • 优先使用 IService 提供的方法! 这是最推荐、最常用的方式。
    • 为什么?
    • 方法名和功能更贴合业务场景(批量操作、智能保存等)。
    • IService 方法默认在事务中执行,保证数据一致性(如批量操作失败会回滚)。
    • 代码简洁一行 saveBatch(list) 比你自己写循环调用 insert并管理事务要简洁安全得多。明确体现了 Service 层调用 Dao 层的分层关系。
  2. 在需要编写非常定制化的复杂 SQL 或特殊查询时:

    • 可以在 UserDao中定义自定义方法 ,并在对应的 Mapper.xml 文件或注解中编写 SQL。
    • 然后在 UserServiceImpl 中,通过 this.getBaseMapper()baseMapper (如果你在实现类中直接注入了 UserDao ) 来调用这些自定义的 Dao 方法。
  3. 在 Controller 或其他非Service类中:

    • 绝对不要 直接注入和使用 BaseMapper必须通过 Service 接口来访问业务功能
    • 这是分层架构的核心原则:Controller 调用 Service,Service 调用 Mapper。直接绕开 Service 层使用 Mapper 会破坏分层,导致事务失效。千万不要这么胡整哦!都没可读性了

五、总结一把

  • BaseMapper:提供直接、原子化的数据库访问能力,是数据持久化的基础。
  • IService:站在业务的角度,在 BaseMapper 的基础上,提供更符合业务需求、而且还有事务管理的一些注解和方法等。

选择的关键在于理解分层:

  1. BaseMapper:专注"如何访问数据库"。
  2. IService:专注"业务逻辑的处理,和数据的一个整合吧",并协调底层数据访问。
相关推荐
韩立学长38 分钟前
【开题答辩实录分享】以《智能大学宿舍管理系统的设计与实现》为例进行选题答辩实录分享
数据库·spring boot·后端
编码者卢布3 小时前
【Azure Storage Account】Azure Table Storage 跨区批量迁移方案
后端·python·flask
她说..6 小时前
策略模式+工厂模式实现审批流(面试问答版)
java·后端·spring·面试·springboot·策略模式·javaee
梦梦代码精6 小时前
开源、免费、可商用:BuildingAI一站式体验报告
开发语言·前端·数据结构·人工智能·后端·开源·知识图谱
李慕婉学姐7 小时前
【开题答辩过程】以《基于Spring Boot的疗养院理疗管理系统的设计与实现》为例,不知道这个选题怎么做的,不知道这个选题怎么开题答辩的可以进来看看
java·spring boot·后端
tb_first7 小时前
SSM速通2
java·javascript·后端
一路向北⁢7 小时前
Spring Boot 3 整合 SSE (Server-Sent Events) 企业级最佳实践(一)
java·spring boot·后端·sse·通信
风象南8 小时前
JFR:Spring Boot 应用的性能诊断利器
java·spring boot·后端
爱吃山竹的大肚肚8 小时前
微服务间通过Feign传输文件,处理MultipartFile类型
java·spring boot·后端·spring cloud·微服务
毕设源码-邱学长10 小时前
【开题答辩全过程】以 基于Springboot的酒店住宿信息管理系统的设计与实现为例,包含答辩的问题和答案
java·spring boot·后端