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

mybatis-plus从入门到入土(三):持久层接口之IService

大家好,之前两周一直没有更新博客,主要因为最近回了趟老家,处理了一些事情。好了,今天我们开始更新第三篇持久层接口。首先先看持久层的IService接口。

官方文档https://baomidou.com/guides/data-interface/#get

IService相关方法

IService是我们工作中最长用到的类,这里面的方法主要就是增删改查,我们先来看几个方法。

// 插入一条记录(选择字段,策略插入)
boolean save(T entity);
// 插入(批量)
boolean saveBatch(Collection<T> entityList);
// 插入(批量)
boolean saveBatch(Collection<T> entityList, int batchSize);

关于增,也就是插入记录,在这个接口里主要提供了单条插入批量插入方法,关于saveBatch的两个方法需要说一下,虽然一个带有batchSize,一个不带,但是最终都是走的带batchSize的方法。如果不指定batchSize,则batchSize为1000。有兴趣的可以看下源码。

// 根据 queryWrapper 设置的条件,删除记录
boolean remove(Wrapper<T> queryWrapper);
// 根据 ID 删除
boolean removeById(Serializable id);
// 根据 columnMap 条件,删除记录
boolean removeByMap(Map<String, Object> columnMap);
// 删除(根据ID 批量删除)
boolean removeByIds(Collection<? extends Serializable> idList);

关于删,有根据id删除,也有根据条件删除,总体都比较简单就不赘述了。

// 根据 UpdateWrapper 条件,更新记录 需要设置sqlset
boolean update(Wrapper<T> updateWrapper);
// 根据 whereWrapper 条件,更新记录
boolean update(T updateEntity, Wrapper<T> whereWrapper);
// 根据 ID 选择修改
boolean updateById(T entity);
// 根据ID 批量更新
boolean updateBatchById(Collection<T> entityList);
// 根据ID 批量更新
boolean updateBatchById(Collection<T> entityList, int batchSize);

关于改,其他几个方法也没啥,可以单条更新,可以批量更新,UpdateWrapper说一下,这是个更新包装器,可以用来组装更新的字段和条件等,这个后面会讲到。


--------------------------GET 单条查询-----------------------------------------------------------------------
// 根据 ID 查询
T getById(Serializable id);
// 根据 Wrapper,查询一条记录。结果集,如果是多个会抛出异常,随机取一条加上限制条件 wrapper.last("LIMIT 1")
T getOne(Wrapper<T> queryWrapper);--------------------------LIST 集合查询-----------------------------------------------------------------------
// 查询所有
List<T> list();
// 查询列表
List<T> list(Wrapper<T> queryWrapper);
// 查询(根据ID 批量查询)
Collection<T> listByIds(Collection<? extends Serializable> idList);
// 查询(根据 columnMap 条件)
Collection<T> listByMap(Map<String, Object> columnMap);--------------------------PAGE 分页查询-----------------------------------------------------------------------
// 无条件分页查询
IPage<T> page(IPage<T> page);
// 条件分页查询
IPage<T> page(IPage<T> page, Wrapper<T> queryWrapper);--------------------------COUNT 数量查询-----------------------------------------------------------------------
// 查询总记录数
long count();
// 根据 Wrapper 条件,查询总记录数
long count(Wrapper<T> queryWrapper);

关于查,分为单条查询集合查询分页查询数量查询;这几个API用法也比较简单,这里简单列举了一些,但是不全;建议去看下官方文档的描述。

以上就是增删改查的部分API,大家可能感到很无语,我基本上只是把方法贴上去了,但是确实没啥可讲的,对着官方文档的例子,大家自己测试下就好了,当然我还省略了saveOrUpdate方法,这个主要是根据主键来判断是更新还是删除。下面我们分析下IService的继承结构,这块是我重点想讲的,对这些了解了,才是对大家真正的有帮助。

IService相关类结构

在这里插入图片描述
从上面图中,可以看出,IService继承自IRepository,然后IRepository还有个抽象实现类AbstractRepository,以及CrudRepository,最后呢有一个ServiceImpl继承了CrudRepository还实现了IService接口。是不是听晕了,没关系,我们挨个来看下。

IRepository

IRepository作为顶层接口,它实现了增删改查里面的比较基础的方法,比如savedeleteById等,但是涉及到批量操作的或者需要一些逻辑判断的是交给实现类去实现的。如下图所示在IRepository接口中只实现了save方法,但是save方法的getBaseMapper也没有实现,也就是说getBaseMapper也是需要实现类去定义逻辑的。

    /*** 插入一条记录(选择字段,策略插入)** @param entity 实体对象*/default boolean save(T entity) {return SqlHelper.retBool(getBaseMapper().insert(entity));}/*** 插入(批量)** @param entityList 实体对象集合* @param batchSize  插入批次数量*/boolean saveBatch(Collection<T> entityList, int batchSize);/*** 批量修改插入** @param entityList 实体对象集合* @param batchSize  每次的数量*/boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize);...省略其他方法.../*** 获取对应 entity 的 BaseMapper** @return BaseMapper*/BaseMapper<T> getBaseMapper();

AbstractRepository

AbstractRepository作为抽象类,在IRepository的基础上填充了不少的方法逻辑,比如批量操作的一些方法,还有saveOrUpdate以及getOne这类的方法也是在AbstractRepository中实现的,从这一点可以看出来,作者设计的时候把IRepository作为绝对的顶层接口,只实现非常简单单一的增删改查。

...省略其他方法...
@Override
public boolean saveOrUpdate(T entity) {return getBaseMapper().insertOrUpdate(entity);
}@Override
public T getOne(Wrapper<T> queryWrapper, boolean throwEx) {return getBaseMapper().selectOne(queryWrapper, throwEx);
}

CrudRepository

CrudRepository最重要的点,就是在这个类里面实现了getBaseMapper,也就意味着之前IRepositoryAbstractRepository一直缺少的BaseMapper,终于有了,就是相当于之前都是定义了一些逻辑和规则,但缺少真正的引擎啊,好了,CrudRepository是真真正正的能执行的个体了。

/*** IService 实现类( 泛型:M 是 mapper 对象,T 是实体 )** @author hubin* @since 2018-06-23*/
public abstract class CrudRepository<M extends BaseMapper<T>, T> extends AbstractRepository<M, T> {@Autowiredprotected M baseMapper;@Overridepublic M getBaseMapper() {Assert.notNull(this.baseMapper, "baseMapper can not be null");return this.baseMapper;}...省略其他方法...
}

IService

好了,我们再看下IService这个接口的意义是什么,我们之前已经看到了从IRepository一直到CrudRepository,这之间从单一的增删改查到批量操作以至最后的装上引擎,这已经够了啊,那IService是干什么的呢?

IService中只定义了下面这四个方法,都是关于批量操作的,但是方法内的逻辑还是直接调用了IRepository的对应方法,唯一的区别就是他把这四个方法都加上了事务注解,这也就是这个接口为什么叫做IService的原因,这是真正贴合实际开发中需要的MVC三层架构中Service服务的接口,他对于批量的操作进行了事务控制,正如咱们平时开发的时候需要在Service类中加事务注解一样,从这可以看出MybatisPlus的作者在类的设计上还是很讲究的奥。

public interface IService<T> extends IRepository<T> {/*** 插入(批量)** @param entityList 实体对象集合*/@Transactional(rollbackFor = Exception.class)default boolean saveBatch(Collection<T> entityList) {return saveBatch(entityList, DEFAULT_BATCH_SIZE);}/*** 批量修改插入** @param entityList 实体对象集合*/@Transactional(rollbackFor = Exception.class)default boolean saveOrUpdateBatch(Collection<T> entityList) {return saveOrUpdateBatch(entityList, DEFAULT_BATCH_SIZE);}/*** 批量删除(jdbc批量提交)** @param list 主键ID或实体列表(主键ID类型必须与实体类型字段保持一致)* @return 删除结果* @since 3.5.0*/@Transactional(rollbackFor = Exception.class)default boolean removeBatchByIds(Collection<?> list) {return removeByIds(list);}/*** 根据ID 批量更新** @param entityList 实体对象集合*/@Transactional(rollbackFor = Exception.class)default boolean updateBatchById(Collection<T> entityList) {return updateBatchById(entityList, DEFAULT_BATCH_SIZE);}
}

ServiceImpl

好了,轮到最后的重头戏了,就是ServiceImpl类,这个类没有任何的方法,但是他继承了CrudRepository并且实现了IService接口,从这个类的定位来说,首先他实现IService接口,证明他是用于提供Service服务层级的实现类,然后继承CrudRepository呢,是为了获取CrudRepository中一些已经实现的功能。话说是不是有个什么设计模式和这很像来着??

/*** IService 实现类( 泛型:M 是 mapper 对象,T 是实体 )** @author hubin* @since 2018-06-23*/
public class ServiceImpl<M extends BaseMapper<T>, T> extends CrudRepository<M, T> implements IService<T> {}

什么设计模式和这很像来着??**

/*** IService 实现类( 泛型:M 是 mapper 对象,T 是实体 )** @author hubin* @since 2018-06-23*/
public class ServiceImpl<M extends BaseMapper<T>, T> extends CrudRepository<M, T> implements IService<T> {}

好了,朋友们,今天先讲到这里吧。想必经过今天的讲解大家对IService这个接口的理解更加深了吧,我们下周再会!

http://www.xdnf.cn/news/16527.html

相关文章:

  • Day 22: 复习
  • OTG原理讲解
  • 进制间的映射关系
  • 【RHCSA 问答题】第 12 章 安装和更新软件包
  • WorkManager vs Flow 适用场景分析
  • CSS变量与Houdini自定义属性:解锁样式编程新维度
  • [硬件电路-94]:模拟器件 - 信号耦合,让被放大信号与静态工作点的直流偏置信号完美的融合
  • 慧星云新增大模型服务:多款大模型轻松调用
  • 编程语言Java——核心技术篇(四)集合类详解
  • Go的内存管理和垃圾回收
  • 震网(Stuxnet):打开潘多拉魔盒的数字幽灵
  • 网络:基础概念
  • React入门指南——指北指南(第二节)
  • 深入浅出学习 KNN 算法:从原理到数字识别实践
  • 【简述】C++11/14/17/20/23 中的关键新特性
  • 从UX到AX:从“设计路径”到“共创关系”的范式革命——Agentic Experience如何重塑未来产品哲学
  • 秋招Day19 - 分布式 - 限流
  • 数据科学与大数据技术专业的核心课程体系及发展路径全解析
  • 从0开始学linux韦东山教程Linux驱动入门实验班(5)
  • 基于华为ENSP的OSPFLSA深入浅出-0
  • 元宇宙新基建:重塑数字市场的“超大陆”边界
  • LeetCode 895:最大频率栈
  • 6G通感算
  • 利用DeepSeek解决kdb+x进行tpch测试的几个问题及使用感受
  • 阿里开源Qwen3-Coder,编程大模型进入高效时代
  • [Python] -进阶理解7- Python中的内存管理机制简析
  • 详解Aerospike数据库在Linux系统上的安装流程
  • Django项目开发技巧
  • MySQL相关概念和易错知识点(2)(表结构的操作、数据类型、约束)
  • 零基础学习性能测试第三章:jmeter线程组组合