当前位置: 首页 > news >正文

深入理解 MyBatis-Plus 的 `ServiceImpl`

在使用 MyBatis-Plus 时,除了熟悉 BaseMapper 接口,很多开发者还会接触到 ServiceImpl —— 它是 MyBatis-Plus 提供的一个 通用业务层基础实现类。合理理解与使用 ServiceImpl,可以极大地简化 Service 层的 CRUD 编码工作,提升开发效率。


一、背景与定位

在典型的三层架构中:

  • Controller 层:接收请求、返回结果
  • Service 层:业务逻辑编排
  • DAO 层 (Mapper):直接操作数据库

MyBatis-Plus 提供了 BaseMapper 简化了 DAO 层的 CRUD,而在 Service 层,通常需要编写一堆相似的增删改查逻辑。为此,MyBatis-Plus 提供了 IService 接口 + ServiceImpl 实现类,将通用逻辑抽象出来。

其主要类关系如下:

IService<T>   ←——  通用 Service 接口(定义通用方法)↑
ServiceImpl<M extends BaseMapper<T>, T>   ←——  通用 Service 实现类↑
自定义 Service 实现类(继承 ServiceImpl)

二、源码结构

ServiceImpl 位于:

package com.baomidou.mybatisplus.extension.service.impl;

其类定义大致如下:

public class ServiceImpl<M extends BaseMapper<T>, T> implements IService<T> {@Autowiredprotected M baseMapper;@Overridepublic boolean save(T entity) { ... }@Overridepublic boolean removeById(Serializable id) { ... }@Overridepublic T getById(Serializable id) { ... }@Overridepublic boolean updateById(T entity) { ... }@Overridepublic List<T> list() { ... }@Overridepublic Page<T> page(Page<T> page, Wrapper<T> queryWrapper) { ... }// 其他更多通用方法 ...
}

关键点:

  • 泛型 M:指定对应的 Mapper,即 DAO 层
  • 泛型 T:指定实体类
  • baseMapper:自动注入,承载底层数据库操作
  • 方法实现:大部分方法直接委托给 BaseMapper

三、使用方式

1. 定义实体与 Mapper

@Data
@TableName("user")
public class User {private Long id;private String name;private Integer age;
}
@Mapper
public interface UserMapper extends BaseMapper<User> {
}

2. 定义 Service 接口与实现

public interface UserService extends IService<User> {// 可以扩展自定义方法
}
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>implements UserService {
}

3. 在 Controller 中调用

@RestController
@RequestMapping("/user")
public class UserController {@Autowiredprivate UserService userService;@PostMapping("/add")public String addUser(@RequestBody User user) {return userService.save(user) ? "ok" : "fail";}@GetMapping("/{id}")public User getUser(@PathVariable Long id) {return userService.getById(id);}
}

这样,一个基础的 CRUD 就完成了,几乎无需自己写实现逻辑。


四、常用方法分类

ServiceImpl 提供了大量常用方法,可以归类如下:

1. 新增

  • save(T entity)
  • saveBatch(Collection<T> entityList)
  • saveOrUpdate(T entity)

2. 删除

  • removeById(Serializable id)
  • removeByIds(Collection<? extends Serializable> idList)
  • remove(Wrapper<T> queryWrapper)

3. 修改

  • updateById(T entity)
  • update(T entity, Wrapper<T> updateWrapper)
  • updateBatchById(Collection<T> entityList)

4. 查询

  • getById(Serializable id)
  • listByIds(Collection<? extends Serializable> idList)
  • list(Wrapper<T> queryWrapper)
  • page(Page<T> page, Wrapper<T> queryWrapper)
  • getOne(Wrapper<T> queryWrapper)

5. 统计与判断

  • count()
  • exists(Wrapper<T> queryWrapper)

五、常见问题

1. 必须继承 ServiceImpl 吗?

不是必须。你也可以只用 BaseMapper,在 Controller 里直接调用。但这样会让业务层缺失,代码耦合度较高,推荐通过 ServiceImpl 来隔离业务逻辑与持久化

2. 如果要写自定义方法怎么办?

直接在 Service 接口和实现类中新增即可,比如:

@Override
public List<User> findByAge(Integer age) {return lambdaQuery().eq(User::getAge, age).list();
}

3. 与 Mapper 的关系?

  • Mapper:最贴近数据库,负责 SQL 层
  • ServiceImpl:封装 Mapper,并为业务提供统一接口

六、最佳实践

  1. 接口分离:定义 Service 接口,避免直接在 Controller 注入 ServiceImpl
  2. 扩展业务逻辑:在继承的 ServiceImpl 上增加自己的方法,不要随意修改通用方法
  3. 批量操作:使用 saveBatchupdateBatchById 提升性能
  4. LambdaQueryWrapper:结合 ServiceImpl 的查询方法,写法更简洁安全

七、总结

ServiceImpl 是 MyBatis-Plus 提供的 通用业务实现基类,它:

  • 封装了常用 CRUD 逻辑
  • 统一了 Service 层接口风格
  • 提升了开发效率与代码可维护性

文章转载自:

http://1mzOZ7Th.kzrbn.cn
http://TdqYmzhs.kzrbn.cn
http://HsllfT9g.kzrbn.cn
http://ezr6GE3C.kzrbn.cn
http://mi1w9VM9.kzrbn.cn
http://mz5IztHC.kzrbn.cn
http://MMh92GLI.kzrbn.cn
http://5QRH7ah2.kzrbn.cn
http://lHoE0MNg.kzrbn.cn
http://x0dpxatw.kzrbn.cn
http://oDVIXr0t.kzrbn.cn
http://BJn8UXlK.kzrbn.cn
http://cscNzpaG.kzrbn.cn
http://CRB8HWdQ.kzrbn.cn
http://YisL6XbW.kzrbn.cn
http://9LJWIYwF.kzrbn.cn
http://ptoZ1rRo.kzrbn.cn
http://75fGfru9.kzrbn.cn
http://ro4C4x7S.kzrbn.cn
http://q2rAaty7.kzrbn.cn
http://Mc2s8d8K.kzrbn.cn
http://3mDtFbX8.kzrbn.cn
http://bdQqT9VN.kzrbn.cn
http://yDVHdT7v.kzrbn.cn
http://p0kr9JQ4.kzrbn.cn
http://KVcHXa3H.kzrbn.cn
http://hxhpLFso.kzrbn.cn
http://ay1EP21O.kzrbn.cn
http://BlBlmw1E.kzrbn.cn
http://Jr9Rbu7o.kzrbn.cn
http://www.dtcms.com/a/373073.html

相关文章:

  • 软件可靠性定量核心指标与关系深入解析
  • Android音频学习(十七)——音频数据流转
  • 如何一次性将多个PPT幻灯片批量转换成PDF文档
  • Vue响应式底层原理:深入解析依赖追踪机制
  • 抖音批量上传视频怎么弄?抖音矩阵账号管理的专业指南
  • 数学知识--行向量与矩阵相乘,和矩阵与行向量相乘的区别
  • 【硬件-笔试面试题-70】硬件/电子工程师,笔试面试题(知识点:过压保护电路)
  • PostgreSQL打印实时查询语句(监控PostgreSQL监控)(未成功)
  • “代练护航”小程序API源码搭建:高并发接单系统的技术突破与实战,多端适配与跨平台开发 如何覆盖微信、H5、APP全场景?
  • 从航空FACE的一个落地方案漫谈汽车HPC软件架构的思维转变(1/3)FACE基础概念与落地案例
  • Docker多共享网络配置策略(Docker多网络、Docker networks、Docker Compose网络、Docker网络、Docker共享网络)
  • Terraform 从入门到实战:历史、原理、功能与阿里云/Azure 上手指南
  • 阿里云国际代理:稳定、高效、便捷的数据库服务-云数据库RDS
  • Django中的软删除
  • PyCharm旧版本下载地址
  • 华为USG6000v2 NAT模式下IPSEC IKE V1 实验
  • 深入实践G1垃圾收集器调优:Java应用性能优化实战指南
  • sqlite3的使用
  • LeetCode Hot 100 Python (81~90)
  • LeetCode 面试经典 150 题:删除有序数组中的重复项(双指针思想解法详解)
  • apifox的post的表单提交的gbk的解决方案
  • leetcode算法刷题的第二十九天
  • 绿联科技全球化突围:业财一体化如何打通全球电商全链路数字化
  • golang-gin包
  • SpringAI调用MCP服务的实现思路
  • react16到react19更新及底层实现是什么以及区别
  • K-meas 聚类、KNN算法、决策树、随机森林
  • Day 17: 3D点云深度学习专项 - 理论深度与面试精通之路
  • React中的合成事件
  • 不连续页分配器补充