Mybatis-Plus中Service层和Mapper层提供的常见方法有哪些?
一、Mapper 层:BaseMapper<T> 接口
这是最底层、最接近数据库的一层。只要你的 UserMapper 接口继承了 BaseMapper<User>,它就自动拥有了以下所有方法。这些方法是所有上层方法的基础。
核心特点:
- 面向数据:方法名都是动词+名词的形式,如
selectById,insert,非常直观。 - 参数直接:参数通常是实体
T、主键Serializable或Wrapper。 - 返回直接:返回值是影响的行数
int、实体T或列表List<T>。
常用方法列表:
【插入】
insert(T entity): 插入一条记录。
【删除】
deleteById(Serializable id): 根据主键删除。deleteByMap(Map<String, Object> columnMap): 根据 Map 条件删除。deleteBatchIds(Collection<? extends Serializable> idList): 批量删除。delete(Wrapper<T> wrapper): 根据条件构造器删除。
【修改】
updateById(T entity): 根据主键更新(只更新非null字段)。update(T entity, Wrapper<T> updateWrapper): 根据条件构造器更新。
【查询】
selectById(Serializable id): 根据主键查询。selectBatchIds(Collection<? extends Serializable> idList): 批量查询。selectByMap(Map<String, Object> columnMap): 根据 Map 条件查询。selectOne(Wrapper<T> wrapper): 查询一条记录(结果多于1条会报错)。selectCount(Wrapper<T> wrapper): 查询总记录数。selectList(Wrapper<T> wrapper): (极其常用) 查询列表。selectMaps(Wrapper<T> wrapper): 查询列表,结果是List<Map>。selectObjs(Wrapper<T> wrapper): 查询列表,只返回第一列的值。
【分页查询】
selectPage(IPage<T> page, Wrapper<T> wrapper): (极其常用) 分页查询。selectMapsPage(IPage<Map<String, Object>> page, Wrapper<T> wrapper): 分页查询,结果是List<Map>。
二、Service 层:IService<T> 接口 & ServiceImpl<M, T> 实现类
Service 层是面向业务的一层。它封装了对 Mapper 层的调用,并提供了一些更方便、更业务化的方法。你的 UserService 接口通常会继承 IService<User>,而实现类 UserServiceImpl 会继承 ServiceImpl<UserMapper, User>。
核心特点:
- 面向业务:方法名更贴近业务操作,如
save,remove,list。 - 封装逻辑:对 Mapper 的调用进行了封装,比如将
insert > 0的判断封装在save方法中,直接返回boolean。 - 功能增强:提供了一些 Mapper 层没有的便捷方法,特别是批量操作。
常用方法列表:
【单个操作 (基本是对 Mapper 的封装)】
save(T entity): 保存一条记录。内部调用mapper.insert(),返回boolean。removeById(Serializable id): 根据主键删除。返回boolean。updateById(T entity): 根据主'键更新。返回boolean。getById(Serializable id): 根据主键查询。getOne(Wrapper<T> queryWrapper, boolean throwEx): 查询一条记录。throwEx参数可以控制当结果不唯一时是否抛出异常。count()/count(Wrapper<T> queryWrapper): 查询总数。list()/list(Wrapper<T> queryWrapper): 查询列表。page(IPage<T> page, Wrapper<T> queryWrapper): 分页查询。
【批量操作 (Service 层的增强亮点!)】
这些方法在 BaseMapper 中是没有的,ServiceImpl 内部通过循环或批处理的方式实现,非常方便。
saveBatch(Collection<T> entityList): 批量插入。saveOrUpdateBatch(Collection<T> entityList): 批量插入或更新(根据主键是否存在)。removeByIds(Collection<? extends Serializable> idList): 批量删除。updateBatchById(Collection<T> entityList): 批量更新。
【插入或更新】
saveOrUpdate(T entity): 根据实体的主键是否存在,自动判断是执行insert还是update。在表单提交等场景中非常有用。
三、Mapper 层 vs Service 层:一张对比图
| 对比维度 | BaseMapper (Mapper 层) |
IService / ServiceImpl (Service 层) |
|---|---|---|
| 定位 | 数据访问层 (DAO),直接与数据库交互。 | 业务逻辑层,封装和编排业务,调用 Mapper。 |
| 方法命名 | 数据操作导向 (e.g., selectById, insert) |
业务操作导向 (e.g., getById, save) |
| 返回值 | 更原始,如返回影响行数 int。 |
更友好,如将 int > 0 转换为 boolean。 |
| 核心能力 | 提供所有基础的、原子的数据库 CRUD 操作。 | 在 Mapper 基础上,封装了常用逻辑,并提供了强大的批量操作。 |
| 典型调用 | userMapper.selectById(1L); |
userService.getById(1L); |
Wrapper 用法 |
userMapper.selectList(wrapper); |
userService.list(wrapper); |
| 特色功能 | 分页查询 selectPage 是其核心功能之一。 |
批量操作 saveBatch, removeByIds 等是其独有的亮点。 |
总结与最佳实践
-
在
Service实现类 (UserServiceImpl) 内部,你应该优先使用Service层自身提供的方法。例如,用this.getById()而不是baseMapper.selectById(),用this.saveBatch()而不是自己去循环调用baseMapper.insert()。因为ServiceImpl提供了更好的封装和增强功能。 -
BaseMapper是ServiceImpl的基础。ServiceImpl内部所有对数据库的操作,最终都是委托给它注入的baseMapper来完成的。 -
当需要编写自定义 SQL 时,方法应该定义在
Mapper接口 (UserMapper) 中,然后在Service层通过注入的userMapper实例来调用。
这个分层设计非常清晰:Controller -> Service -> Mapper。
Controller调用Service的业务方法。Service实现业务逻辑,优先使用IService提供的便捷方法(内部调用Mapper),如果功能不足,再直接调用Mapper的方法(包括自定义的 SQL 方法)。Mapper负责最终的数据库交互。

浙公网安备 33010602011771号