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

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

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

IService相关方法

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

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

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

java 复制代码
// 根据 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删除,也有根据条件删除,总体都比较简单就不赘述了。

java 复制代码
// 根据 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说一下,这是个更新包装器,可以用来组装更新的字段和条件等,这个后面会讲到。

java 复制代码
--------------------------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也是需要实现类去定义逻辑的。

java 复制代码
    /**
     * 插入一条记录(选择字段,策略插入)
     *
     * @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作为绝对的顶层接口,只实现非常简单单一的增删改查。

java 复制代码
...省略其他方法...
@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是真真正正的能执行的个体了。

java 复制代码
/**
 * IService 实现类( 泛型:M 是 mapper 对象,T 是实体 )
 *
 * @author hubin
 * @since 2018-06-23
 */
public abstract class CrudRepository<M extends BaseMapper<T>, T> extends AbstractRepository<M, T> {

    @Autowired
    protected M baseMapper;

    @Override
    public 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的作者在类的设计上还是很讲究的奥。

java 复制代码
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中一些已经实现的功能。话说是不是有个什么设计模式和这很像来着??

java 复制代码
/**
 * 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> {

}

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

java 复制代码
/**
 * 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这个接口的理解更加深了吧,我们下周再会!

相关推荐
苦学编程的谢12 小时前
MyBatis_3
java·开发语言·后端·mybatis
guojl12 小时前
MyBatis最佳实践
后端·微服务·mybatis
小白的代码日记14 小时前
MyBatis-Plus 通用 Service
mybatis
Java初学者小白1 天前
秋招Day18 - MyBatis - 基础
java·数据库·mybatis
经典19921 天前
Spring Boot 遇上 MyBatis-Plus:高效开发的奇妙之旅
java·spring boot·mybatis
艺杯羹2 天前
MyBatis 之缓存机制核心解析
java·后端·spring·mybatis
鹦鹉0072 天前
mybatis多对一一对多的关联及拼接操作以及缓存处理
缓存·mybatis
心月狐的流火号3 天前
Mybatis 分页插件 PageHelper SQL异常拼接问题深度分析
java·mybatis
南清的coding日记3 天前
苍穹外卖DAY11
java·开发语言·spring boot·spring·mvc·mybatis