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

MyBatisPlus(SpringBoot版)学习第三讲:通用Service

目录

1. 前言

2. IService

IService原码

ServiceImpl原码

3.创建Service接口和实现类

4. 测试

4.1 插入

1> 插入单个实体类

2> 批量保存,使用默认批量大小

3> 批量保存,指定批量大小

4> 批量保存或更新,使用默认批量大小

5> 批量保存或更新,指定批量大小

4.2 删除

1> 根据实体对象ID删除

2> 根据实体对象ID删除,支持使用填充

3> 根据实体对象删除

4>  根据columnMap删除

5>  根据查询条件包装器queryWrapper删除

6> 根据ID列表批量删除

7>  根据ID列表批量删除,支持使用填充

8> 根据ID列表批量删除,使用默认批量大小

9> 根据ID列表批量删除,使用默认批量大小并使用填充

10> 根据ID列表批量删除,指定批量大小

11> 根据ID列表批量删除,指定批量大小和是否使用填充

4.3 修改

1> 根据ID修改

2>  根据修改条件包装器修改

3>  根据实体对象和修改条件包装器修改

 4> 根据ID批量修改,使用默认批量大小

5> 根据ID批量修改,指定批量大小

6> 保存或更新单个实体对象

4.4 查询

1> 根据实体对象的ID获取该对象

2> 根据ID列表获取实体对象列表

3> 根据条件映射获取实体对象列表

4> 根据查询条件包装器获取单个实体对象,默认抛出异常时返回对象

5>  根据查询条件包装器获取单个实体对象,指定是否抛出异常

6> 根据查询条件包装器获取单个结果的Map表示

7> 根据查询条件包装器获取单个结果,并通过Function进行转换

8> 统计总数

9> 剩下的一些(查总数,添加分页,转换函数,链式包装器):


1. 前言

说明:

   通用 Service CRUD 封装IService接口,进一步封装 CRUD 采用  get 查询单行  remove 删除  list 查询集合   page 分页  前缀命名方式区分  Mapper 层避免混淆,

   泛型 T 为任意实体对象

  建议如果存在自定义通用 Service 方法的可能,请创建自己的  IBaseService  继承Mybatis-Plus 提供的基类

   官网地址:  https://baomidou.com/pages/49cc81/#service-crud-%E6%8E%A5%E5%8F% A3


2. IService

         MyBatis-Plus中有一个接口 IService和其实现类 ServiceImpl,封装了常见的业务层逻辑

详情查看源码IService和ServiceImpl

IService原码

        接口是一种抽象类型,只包含抽象方法、默认方法、静态方法和常量。

默认方法

        与抽象方法不同,默认方法使用 

        default 关键字来定义,并且拥有具体的方法体。这意味着当一个类实现了包含默认方法的接口时,并不强制要求该类去重写这个默认方法,因为它已经有了默认的实现逻辑。

        实现类可以直接使用接口中的默认方法,就像使用自己类里的方法一样。同时,实现类也可以选择重写默认方法,以提供自定义的实现逻辑。

// 定义一个泛型接口 IService,T 代表实体类类型
public interface IService<T> {
    // 定义默认的批量操作大小常量,值为 1000
    int DEFAULT_BATCH_SIZE = 1000;

    /**
     * 保存单个实体对象到数据库
     * @param entity 要保存的实体对象
     * @return 保存操作是否成功的布尔值
     */
    default boolean save(T entity) {
        // 调用基础映射器的 insert 方法插入实体对象,并通过 SqlHelper 将结果转换为布尔值
        return SqlHelper.retBool(this.getBaseMapper().insert(entity));
    }

    /**
     * 批量保存实体对象到数据库,使用默认批量大小
     * @param entityList 要保存的实体对象集合
     * @return 批量保存操作是否成功的布尔值
     */
    @Transactional(
        rollbackFor = {Exception.class}
    )
    default boolean saveBatch(Collection<T> entityList) {
        // 调用带批量大小参数的 saveBatch 方法,使用默认批量大小 1000
        return this.saveBatch(entityList, 1000);
    }

    /**
     * 批量保存实体对象到数据库,指定批量大小
     * @param var1 要保存的实体对象集合
     * @param var2 批量大小
     * @return 批量保存操作是否成功的布尔值
     */
    boolean saveBatch(Collection<T> var1, int var2);

    /**
     * 批量保存或更新实体对象到数据库,使用默认批量大小
     * @param entityList 要保存或更新的实体对象集合
     * @return 批量保存或更新操作是否成功的布尔值
     */
    @Transactional(
        rollbackFor = {Exception.class}
    )
    default boolean saveOrUpdateBatch(Collection<T> entityList) {
        // 调用带批量大小参数的 saveOrUpdateBatch 方法,使用默认批量大小 1000
        return this.saveOrUpdateBatch(entityList, 1000);
    }

    /**
     * 批量保存或更新实体对象到数据库,指定批量大小
     * @param var1 要保存或更新的实体对象集合
     * @param var2 批量大小
     * @return 批量保存或更新操作是否成功的布尔值
     */
    boolean saveOrUpdateBatch(Collection<T> var1, int var2);

    /**
     * 根据实体对象的 ID 删除该对象
     * @param id 要删除的实体对象的 ID
     * @return 删除操作是否成功的布尔值
     */
    default boolean removeById(Serializable id) {
        // 调用基础映射器的 deleteById 方法删除对象,并通过 SqlHelper 将结果转换为布尔值
        return SqlHelper.retBool(this.getBaseMapper().deleteById(id));
    }

    /**
     * 根据实体对象的 ID 删除该对象,支持使用填充(可能是逻辑删除时的字段填充)
     * @param id 要删除的实体对象的 ID
     * @param useFill 是否使用填充
     * @return 删除操作是否成功的布尔值
     * @throws UnsupportedOperationException 默认抛出此异常,需实现类重写
     */
    default boolean removeById(Serializable id, boolean useFill) {
        throw new UnsupportedOperationException("不支持的方法!");
    }

    /**
     * 根据实体对象删除该对象
     * @param entity 要删除的实体对象
     * @return 删除操作是否成功的布尔值
     */
    default boolean removeById(T entity) {
        // 调用基础映射器的 deleteById 方法删除对象,并通过 SqlHelper 将结果转换为布尔值
        return SqlHelper.retBool(this.getBaseMapper().deleteById(entity));
    }

    /**
     * 根据条件映射删除实体对象
     * @param columnMap 条件映射,包含列名和对应的值
     * @return 删除操作是否成功的布尔值
     */
    default boolean removeByMap(Map<String, Object> columnMap) {
        // 确保条件映射不为空
        Assert.notEmpty(columnMap, "error: columnMap must not be empty", new Object[0]);
        // 调用基础映射器的 deleteByMap 方法删除对象,并通过 SqlHelper 将结果转换为布尔值
        return SqlHelper.retBool(this.getBaseMapper().deleteByMap(columnMap));
    }

    /**
     * 根据查询条件包装器删除实体对象
     * @param queryWrapper 查询条件包装器
     * @return 删除操作是否成功的布尔值
     */
    default boolean remove(Wrapper<T> queryWrapper) {
        // 调用基础映射器的 delete 方法删除对象,并通过 SqlHelper 将结果转换为布尔值
        return SqlHelper.retBool(this.getBaseMapper().delete(queryWrapper));
    }

    /**
     * 根据 ID 列表批量删除实体对象
     * @param list 要删除的实体对象的 ID 列表
     * @return 删除操作是否成功的布尔值
     */
    default boolean removeByIds(Collection<?> list) {
        // 如果 ID 列表为空,返回 false;否则调用基础映射器的 deleteBatchIds 方法删除对象,并通过 SqlHelper 将结果转换为布尔值
        return CollectionUtils.isEmpty(list) ? false : SqlHelper.retBool(this.getBaseMapper().deleteBatchIds(list));
    }

    /**
     * 根据 ID 列表批量删除实体对象,支持使用填充(可能是逻辑删除时的字段填充)
     * @param list 要删除的实体对象的 ID 列表
     * @param useFill 是否使用填充
     * @return 删除操作是否成功的布尔值
     */
    @Transactional(
        rollbackFor = {Exception.class}
    )
    default boolean removeByIds(Collection<?> list, boolean useFill) {
        if (CollectionUtils.isEmpty(list)) {
            return false;
        } else {
            // 如果使用填充,调用 removeBatchByIds 方法并传入 true;否则调用基础映射器的 deleteBatchIds 方法删除对象,并通过 SqlHelper 将结果转换为布尔值
            return useFill ? this.removeBatchByIds(list, true) : SqlHelper.retBool(this.getBaseMapper().deleteBatchIds(list));
        }
    }

    /**
     * 根据 ID 列表批量删除实体对象,使用默认批量大小
     * @param list 要删除的实体对象的 ID 列表
     * @return 删除操作是否成功的布尔值
     */
    @Transactional(
        rollbackFor = {Exception.class}
    )
    default boolean removeBatchByIds(Collection<?> list) {
        // 调用带批量大小和填充标志参数的 removeBatchByIds 方法,使用默认批量大小 1000
        return this.removeBatchByIds(list, 1000);
    }

    /**
     * 根据 ID 列表批量删除实体对象,使用默认批量大小并指定是否使用填充
     * @param list 要删除的实体对象的 ID 列表
     * @param useFill 是否使用填充
     * @return 删除操作是否成功的布尔值
     */
    @Transactional(
        rollbackFor = {Exception.class}
    )
    default boolean removeBatchByIds(Collection<?> list, boolean useFill) {
        // 调用带批量大小和填充标志参数的 removeBatchByIds 方法,使用默认批量大小 1000
        return this.removeBatchByIds(list, 1000, useFill);
    }

    /**
     * 根据 ID 列表批量删除实体对象,指定批量大小
     * @param list 要删除的实体对象的 ID 列表
     * @param batchSize 批量大小
     * @return 删除操作是否成功的布尔值
     * @throws UnsupportedOperationException 默认抛出此异常,需实现类重写
     */
    default boolean removeBatchByIds(Collection<?> list, int batchSize) {
        throw new UnsupportedOperationException("不支持的方法!");
    }

    /**
     * 根据 ID 列表批量删除实体对象,指定批量大小和是否使用填充
     * @param list 要删除的实体对象的 ID 列表
     * @param batchSize 批量大小
     * @param useFill 是否使用填充
     * @return 删除操作是否成功的布尔值
     * @throws UnsupportedOperationException 默认抛出此异常,需实现类重写
     */
    default boolean removeBatchByIds(Collection<?> list, int batchSize, boolean useFill) {
        throw new UnsupportedOperationException("不支持的方法!");
    }

    /**
     * 根据实体对象的 ID 更新该对象
     * @param entity 要更新的实体对象
     * @return 更新操作是否成功的布尔值
     */
    default boolean updateById(T entity) {
        // 调用基础映射器的 updateById 方法更新对象,并通过 SqlHelper 将结果转换为布尔值
        return SqlHelper.retBool(this.getBaseMapper().updateById(entity));
    }

    /**
     * 根据更新条件包装器更新实体对象
     * @param updateWrapper 更新条件包装器
     * @return 更新操作是否成功的布尔值
     */
    default boolean update(Wrapper<T> updateWrapper) {
        // 调用带实体对象和更新条件包装器参数的 update 方法,传入 null 作为实体对象
        return this.update((Object)null, updateWrapper);
    }

    /**
     * 根据实体对象和更新条件包装器更新实体对象
     * @param entity 要更新的实体对象
     * @param updateWrapper 更新条件包装器
     * @return 更新操作是否成功的布尔值
     */
    default boolean update(T entity, Wrapper<T> updateWrapper) {
        // 调用基础映射器的 update 方法更新对象,并通过 SqlHelper 将结果转换为布尔值
        return SqlHelper.retBool(this.getBaseMapper().update(entity, updateWrapper));
    }

    /**
     * 根据 ID 批量更新实体对象,使用默认批量大小
     * @param entityList 要更新的实体对象集合
     * @return 批量更新操作是否成功的布尔值
     */
    @Transactional(
        rollbackFor = {Exception.class}
    )
    default boolean updateBatchById(Collection<T> entityList) {
        // 调用带批量大小参数的 updateBatchById 方法,使用默认批量大小 1000
        return this.updateBatchById(entityList, 1000);
    }

    /**
     * 根据 ID 批量更新实体对象,指定批量大小
     * @param var1 要更新的实体对象集合
     * @param var2 批量大小
     * @return 批量更新操作是否成功的布尔值
     */
    boolean updateBatchById(Collection<T> var1, int var2);

    /**
     * 保存或更新单个实体对象
     * @param var1 要保存或更新的实体对象
     * @return 保存或更新操作是否成功的布尔值
     */
    boolean saveOrUpdate(T var1);

    /**
     * 根据实体对象的 ID 获取该对象
     * @param id 要获取的实体对象的 ID
     * @return 获取到的实体对象
     */
    default T getById(Serializable id) {
        // 调用基础映射器的 selectById 方法获取对象
        return this.getBaseMapper().selectById(id);
    }

    /**
     * 根据 ID 列表获取实体对象列表
     * @param idList 要获取的实体对象的 ID 列表
     * @return 获取到的实体对象列表
     */
    default List<T> listByIds(Collection<? extends Serializable> idList) {
        // 调用基础映射器的 selectBatchIds 方法获取对象列表
        return this.getBaseMapper().selectBatchIds(idList);
    }

    /**
     * 根据条件映射获取实体对象列表
     * @param columnMap 条件映射,包含列名和对应的值
     * @return 获取到的实体对象列表
     */
    default List<T> listByMap(Map<String, Object> columnMap) {
        // 调用基础映射器的 selectByMap 方法获取对象列表
        return this.getBaseMapper().selectByMap(columnMap);
    }

    /**
     * 根据查询条件包装器获取单个实体对象,默认抛出异常时返回对象
     * @param queryWrapper 查询条件包装器
     * @return 获取到的单个实体对象
     */
    default T getOne(Wrapper<T> queryWrapper) {
        // 调用带抛出异常标志参数的 getOne 方法,传入 true 表示抛出异常时返回对象
        return this.getOne(queryWrapper, true);
    }

    /**
     * 根据查询条件包装器获取单个实体对象,指定是否抛出异常
     * @param var1 查询条件包装器
     * @param var2 是否抛出异常的标志
     * @return 获取到的单个实体对象
     */
    T getOne(Wrapper<T> var1, boolean var2);

    /**
     * 根据查询条件包装器获取单个结果的 Map 表示
     * @param var1 查询条件包装器
     * @return 获取到的单个结果的 Map 表示
     */
    Map<String, Object> getMap(Wrapper<T> var1);

    /**
     * 根据查询条件包装器获取单个结果,并通过 Function 进行转换
     * @param var1 查询条件包装器
     * @param var2 转换函数
     * @param <V> 转换后的类型
     * @return 转换后的单个结果
     */
    <V> V getObj(Wrapper<T> var1, Function<? super Object, V> var2);

    /**
     * 获取实体对象的总数,使用空的查询条件包装器
     * @return 实体对象的总数
     */
    default long count() {
        // 调用带查询条件包装器参数的 count 方法,传入空的查询条件包装器
        return this.count(Wrappers.emptyWrapper());
    }

    /**
     * 根据查询条件包装器获取实体对象的总数
     * @param queryWrapper 查询条件包装器
     * @return 实体对象的总数
     */
    default long count(Wrapper<T> queryWrapper) {
        // 调用基础映射器的 selectCount 方法获取总数,并通过 SqlHelper 进行结果处理
        return SqlHelper.retCount(this.getBaseMapper().selectCount(queryWrapper));
    }

    /**
     * 根据查询条件包装器获取实体对象列表
     * @param queryWrapper 查询条件包装器
     * @return 获取到的实体对象列表
     */
    default List<T> list(Wrapper<T> queryWrapper) {
        // 调用基础映射器的 selectList 方法获取对象列表
        return this.getBaseMapper().selectList(queryWrapper);
    }

    /**
     * 获取所有实体对象列表,使用空的查询条件包装器
     * @return 获取到的所有实体对象列表
     */
    default List<T> list() {
        // 调用带查询条件包装器参数的 list 方法,传入空的查询条件包装器
        return this.list(Wrappers.emptyWrapper());
    }

    /**
     * 根据分页对象和查询条件包装器进行分页查询
     * @param page 分页对象
     * @param queryWrapper 查询条件包装器
     * @param <E> 分页对象的类型
     * @return 分页查询结果
     */
    default <E extends IPage<T>> E page(E page, Wrapper<T> queryWrapper) {
        // 调用基础映射器的 selectPage 方法进行分页查询
        return this.getBaseMapper().selectPage(page, queryWrapper);
    }

    /**
     * 根据分页对象进行分页查询,使用空的查询条件包装器
     * @param page 分页对象
     * @param <E> 分页对象的类型
     * @return 分页查询结果
     */
    default <E extends IPage<T>> E page(E page) {
        // 调用带分页对象和查询条件包装器参数的 page 方法,传入空的查询条件包装器
        return this.page(page, Wrappers.emptyWrapper());
    }

    /**
     * 根据查询条件包装器获取结果的 Map 列表
     * @param queryWrapper 查询条件包装器
     * @return 获取到的结果的 Map 列表
     */
    default List<Map<String, Object>> listMaps(Wrapper<T> queryWrapper) {
        // 调用基础映射器的 selectMaps 方法获取结果的 Map 列表
        return this.getBaseMapper().selectMaps(queryWrapper);
    }

    /**
     * 获取所有结果的 Map 列表,使用空的查询条件包装器
     * @return 获取到的所有结果的 Map 列表
     */
    default List<Map<String, Object>> listMaps() {
        // 调用带查询条件包装器参数的 listMaps 方法,传入空的查询条件包装器
        return this.listMaps(Wrappers.emptyWrapper());
    }

    /**
     * 获取所有结果的对象列表,使用默认的转换函数
     * @return 获取到的所有结果的对象列表
     */
    default List<Object> listObjs() {
        // 调用带转换函数参数的 listObjs 方法,传入默认的转换函数
        return this.listObjs(Function.identity());
    }

    /**
     * 根据转换函数获取结果的对象列表,使用空的查询条件包装器
     * @param mapper 转换函数
     * @param <V> 转换后的类型
     * @return 获取到的结果的对象列表
     */
    default <V> List<V> listObjs(Function<? super Object, V> mapper) {
        // 调用带查询条件包装器和转换函数参数的 listObjs 方法,传入空的查询条件包装器
        return this.listObjs(Wrappers.emptyWrapper(), mapper);
    }

    /**
     * 根据查询条件包装器获取结果的对象列表,使用默认的转换函数
     * @param queryWrapper 查询条件包装器
     * @return 获取到的结果的对象列表
     */
    default List<Object> listObjs(Wrapper<T> queryWrapper) {
        // 调用带查询条件包装器和转换函数参数的 listObjs 方法,传入默认的转换函数
        return this.listObjs(queryWrapper, Function.identity());
    }

    /**
     * 根据查询条件包装器和转换函数获取结果的对象列表
     * @param queryWrapper 查询条件包装器
     * @param mapper 转换函数
     * @param <V> 转换后的类型
     * @return 获取到的结果的对象列表
     */
    default <V> List<V> listObjs(Wrapper<T> queryWrapper, Function<? super Object, V> mapper) {
        // 调用基础映射器的 selectObjs 方法获取结果列表,过滤掉 null 值,通过转换函数进行转换,最后收集为列表
        return (List)this.getBaseMapper().selectObjs(queryWrapper).stream().filter(Objects::nonNull).map(mapper).collect(Collectors.toList());
    }

    /**
     * 根据分页对象和查询条件包装器进行分页查询,返回结果的 Map 分页对象
     * @param page 分页对象
     * @param queryWrapper 查询条件包装器
     * @param <E> 分页对象的类型
     * @return 分页查询结果的 Map 分页对象
     */
    default <E extends IPage<Map<String, Object>>> E pageMaps(E page, Wrapper<T> queryWrapper) {
        // 调用基础映射器的 selectMapsPage 方法进行分页查询
        return this.getBaseMapper().selectMapsPage(page, queryWrapper);
    }

    /**
     * 根据分页对象进行分页查询,使用空的查询条件包装器,返回结果的 Map 分页对象
     * @param page 分页对象
     * @param <E> 分页对象的类型
     * @return 分页查询结果的 Map 分页对象
     */
    default <E extends IPage<Map<String, Object>>> E pageMaps(E page) {
        // 调用带分页对象和查询条件包装器参数的 pageMaps 方法,传入空的查询条件包装器
        return this.pageMaps(page, Wrappers.emptyWrapper());
    }

    /**
     * 获取基础的 Mapper 对象
     * @return 基础的 Mapper 对象
     */
    BaseMapper<T> getBaseMapper();

    /**
     * 获取实体类的 Class 对象
     * @return 实体类的 Class 对象
     */
    Class<T> getEntityClass();

    /**
     * 获取查询链式包装器
     * @return 查询链式包装器
     */
    default QueryChainWrapper<T> query() {
        // 调用 ChainWrappers 的 queryChain 方法获取查询链式包装器
        return ChainWrappers.queryChain(this.getBaseMapper());
    }

    /**
     * 获取 Lambda 查询链式包装器
     * @return Lambda 查询链式包装器
     */
    default LambdaQueryChainWrapper<T> lambdaQuery() {
        // 调用 ChainWrappers 的 lambdaQueryChain 方法获取 Lambda 查询链式包装器
        return ChainWrappers.lambdaQueryChain(this.getBaseMapper());
    }

    /**
     * 获取 Kt 查询链式包装器
     * @return Kt 查询链式包装器
     */
    default KtQueryChainWrapper<T> ktQuery() {
        // 调用 ChainWrappers 的 ktQueryChain 方法获取 Kt 查询链式包装器
        return ChainWrappers.ktQueryChain(this.getBaseMapper(), this.getEntityClass());
    }

    /**
     * 获取 Kt 更新链式包装器
     * @return Kt 更新链式包装器
     */
    default KtUpdateChainWrapper<T> ktUpdate() {
        // 调用 ChainWrappers 的 ktUpdateChain 方法获取 Kt 更新链式包装器
        return ChainWrappers.ktUpdateChain(this.getBaseMapper(), this.getEntityClass());
    }

    /**
     * 获取更新链式包装器
     * @return 更新链式包装器
     */
    default UpdateChainWrapper<T> update() {
        // 调用 ChainWrappers 的 updateChain 方法获取更新链式包装器
        return ChainWrappers.updateChain(this.getBaseMapper());
    }

    /**
     * 获取 Lambda 更新链式包装器
     * @return Lambda 更新链式包装器
     */
    default LambdaUpdateChainWrapper<T> lambdaUpdate() {
        // 调用 ChainWrappers 的 lambdaUpdateChain 方法获取 Lambda 更新链式包装器
        return ChainWrappers.lambdaUpdateChain(this.getBaseMapper());
    }

    /**
     * 根据实体对象和更新条件包装器保存或更新实体对象
     * @param entity 要保存或更新的实体对象
     * @param updateWrapper 更新条件包装器
     * @return 保存或更新操作是否成功的布尔值
     */
    default boolean saveOrUpdate(T entity, Wrapper<T> updateWrapper) {
        // 先尝试更新操作,如果更新失败则尝试保存或更新操作
        return this.update(entity, updateWrapper) || this.saveOrUpdate(entity);
    }
}

ServiceImpl原码

// 定义一个泛型服务实现类,M 是 BaseMapper 的子类,T 是实体类类型
// 该类实现了 IService 接口,提供了一系列通用的数据库操作方法
public class ServiceImpl<M extends BaseMapper<T>, T> implements IService<T> {
    // 初始化日志对象,用于记录程序运行过程中的信息
    protected Log log = LogFactory.getLog(this.getClass());
    // 通过 Spring 的自动装配机制注入 BaseMapper 的子类实例,用于执行数据库操作
    @Autowired
    protected M baseMapper;
    // 获取实体类的 Class 对象,用于反射操作和获取实体类的元数据
    protected Class<T> entityClass = this.currentModelClass();
    // 获取 BaseMapper 子类的 Class 对象,用于获取 SQL 语句
    protected Class<M> mapperClass = this.currentMapperClass();

    // 无参构造方法
    public ServiceImpl() {
    }

    /**
     * 获取 BaseMapper 实例
     * @return BaseMapper 实例
     */
    public M getBaseMapper() {
        return this.baseMapper;
    }

    /**
     * 获取实体类的 Class 对象
     * @return 实体类的 Class 对象
     */
    public Class<T> getEntityClass() {
        return this.entityClass;
    }

    /**
     * 将 Integer 类型的结果转换为布尔值,该方法已弃用
     * @param result 数据库操作返回的 Integer 结果
     * @return 转换后的布尔值
     */
    @Deprecated
    protected boolean retBool(Integer result) {
        return SqlHelper.retBool(result);
    }

    /**
     * 通过反射获取泛型参数 M 的 Class 对象
     * @return 泛型参数 M 的 Class 对象
     */
    protected Class<M> currentMapperClass() {
        return ReflectionKit.getSuperClassGenericType(this.getClass(), ServiceImpl.class, 0);
    }

    /**
     * 通过反射获取泛型参数 T 的 Class 对象
     * @return 泛型参数 T 的 Class 对象
     */
    protected Class<T> currentModelClass() {
        return ReflectionKit.getSuperClassGenericType(this.getClass(), ServiceImpl.class, 1);
    }

    /**
     * 获取批量操作的 SqlSession,该方法已弃用
     * @return 批量操作的 SqlSession
     */
    @Deprecated
    protected SqlSession sqlSessionBatch() {
        return SqlHelper.sqlSessionBatch(this.entityClass);
    }

    /**
     * 关闭 SqlSession,该方法已弃用
     * @param sqlSession 要关闭的 SqlSession
     */
    @Deprecated
    protected void closeSqlSession(SqlSession sqlSession) {
        SqlSessionUtils.closeSqlSession(sqlSession, GlobalConfigUtils.currentSessionFactory(this.entityClass));
    }

    /**
     * 根据 SqlMethod 获取 SQL 语句,该方法已弃用
     * @param sqlMethod SQL 方法枚举
     * @return SQL 语句
     */
    @Deprecated
    protected String sqlStatement(SqlMethod sqlMethod) {
        return SqlHelper.table(this.entityClass).getSqlStatement(sqlMethod.getMethod());
    }

    /**
     * 批量保存实体对象
     * @param entityList 要保存的实体对象集合
     * @param batchSize 批量操作的大小
     * @return 保存操作是否成功
     */
    @Transactional(rollbackFor = {Exception.class})
    public boolean saveBatch(Collection<T> entityList, int batchSize) {
        // 获取插入单条记录的 SQL 语句
        String sqlStatement = this.getSqlStatement(SqlMethod.INSERT_ONE);
        // 执行批量插入操作
        return this.executeBatch(entityList, batchSize, (sqlSession, entity) -> {
            sqlSession.insert(sqlStatement, entity);
        });
    }

    /**
     * 根据 SqlMethod 获取 SQL 语句
     * @param sqlMethod SQL 方法枚举
     * @return SQL 语句
     */
    protected String getSqlStatement(SqlMethod sqlMethod) {
        return SqlHelper.getSqlStatement(this.mapperClass, sqlMethod);
    }

    /**
     * 保存或更新单个实体对象
     * @param entity 要保存或更新的实体对象
     * @return 操作是否成功
     */
    @Transactional(rollbackFor = {Exception.class})
    public boolean saveOrUpdate(T entity) {
        // 如果实体对象为空,直接返回 false
        if (null == entity) {
            return false;
        } else {
            // 获取实体类的表信息
            TableInfo tableInfo = TableInfoHelper.getTableInfo(this.entityClass);
            // 断言表信息不为空
            Assert.notNull(tableInfo, "error: can not execute. because can not find cache of TableInfo for entity!", new Object[0]);
            // 获取主键属性名
            String keyProperty = tableInfo.getKeyProperty();
            // 断言主键属性名不为空
            Assert.notEmpty(keyProperty, "error: can not execute. because can not find column for id from entity!", new Object[0]);
            // 获取实体对象的主键值
            Object idVal = tableInfo.getPropertyValue(entity, tableInfo.getKeyProperty());
            // 如果主键值不为空且数据库中存在该记录,则更新记录;否则保存记录
            return !StringUtils.checkValNull(idVal) && !Objects.isNull(this.getById((Serializable)idVal)) ? this.updateById(entity) : this.save(entity);
        }
    }

    /**
     * 批量保存或更新实体对象
     * @param entityList 要保存或更新的实体对象集合
     * @param batchSize 批量操作的大小
     * @return 操作是否成功
     */
    @Transactional(rollbackFor = {Exception.class})
    public boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize) {
        // 获取实体类的表信息
        TableInfo tableInfo = TableInfoHelper.getTableInfo(this.entityClass);
        // 断言表信息不为空
        Assert.notNull(tableInfo, "error: can not execute. because can not find cache of TableInfo for entity!", new Object[0]);
        // 获取主键属性名
        String keyProperty = tableInfo.getKeyProperty();
        // 断言主键属性名不为空
        Assert.notEmpty(keyProperty, "error: can not execute. because can not find column for id from entity!", new Object[0]);
        // 执行批量保存或更新操作
        return SqlHelper.saveOrUpdateBatch(this.entityClass, this.mapperClass, this.log, entityList, batchSize, (sqlSession, entity) -> {
            // 获取实体对象的主键值
            Object idVal = tableInfo.getPropertyValue(entity, keyProperty);
            // 判断主键值是否为空或数据库中是否不存在该记录
            return StringUtils.checkValNull(idVal) || CollectionUtils.isEmpty(sqlSession.selectList(this.getSqlStatement(SqlMethod.SELECT_BY_ID), entity));
        }, (sqlSession, entity) -> {
            // 创建参数映射对象
            ParamMap<T> param = new ParamMap();
            param.put("et", entity);
            // 执行更新操作
            sqlSession.update(this.getSqlStatement(SqlMethod.UPDATE_BY_ID), param);
        });
    }

    /**
     * 根据 ID 批量更新实体对象
     * @param entityList 要更新的实体对象集合
     * @param batchSize 批量操作的大小
     * @return 操作是否成功
     */
    @Transactional(rollbackFor = {Exception.class})
    public boolean updateBatchById(Collection<T> entityList, int batchSize) {
        // 获取根据 ID 更新记录的 SQL 语句
        String sqlStatement = this.getSqlStatement(SqlMethod.UPDATE_BY_ID);
        // 执行批量更新操作
        return this.executeBatch(entityList, batchSize, (sqlSession, entity) -> {
            // 创建参数映射对象
            ParamMap<T> param = new ParamMap();
            param.put("et", entity);
            // 执行更新操作
            sqlSession.update(sqlStatement, param);
        });
    }

    /**
     * 根据查询条件获取单个实体对象
     * @param queryWrapper 查询条件包装器
     * @param throwEx 是否抛出异常
     * @return 单个实体对象
     */
    public T getOne(Wrapper<T> queryWrapper, boolean throwEx) {
        // 如果 throwEx 为 true,则直接调用 baseMapper 的 selectOne 方法;否则调用 SqlHelper 的 getObject 方法
        return throwEx ? this.baseMapper.selectOne(queryWrapper) : SqlHelper.getObject(this.log, this.baseMapper.selectList(queryWrapper));
    }

    /**
     * 根据查询条件获取单个结果的 Map 表示
     * @param queryWrapper 查询条件包装器
     * @return 单个结果的 Map 表示
     */
    public Map<String, Object> getMap(Wrapper<T> queryWrapper) {
        // 调用 SqlHelper 的 getObject 方法获取单个结果的 Map 表示
        return (Map)SqlHelper.getObject(this.log, this.baseMapper.selectMaps(queryWrapper));
    }

    /**
     * 根据查询条件获取单个结果,并通过 Function 进行转换
     * @param queryWrapper 查询条件包装器
     * @param mapper 转换函数
     * @param <V> 转换后的类型
     * @return 转换后的单个结果
     */
    public <V> V getObj(Wrapper<T> queryWrapper, Function<? super Object, V> mapper) {
        // 调用 SqlHelper 的 getObject 方法获取转换后的单个结果
        return SqlHelper.getObject(this.log, this.listObjs(queryWrapper, mapper));
    }

    /**
     * 执行批量操作,该方法已弃用
     * @param consumer 批量操作的消费者
     * @return 操作是否成功
     */
    @Deprecated
    protected boolean executeBatch(Consumer<SqlSession> consumer) {
        return SqlHelper.executeBatch(this.entityClass, this.log, consumer);
    }

    /**
     * 执行批量操作
     * @param list 要操作的对象集合
     * @param batchSize 批量操作的大小
     * @param consumer 批量操作的消费者
     * @param <E> 对象集合的元素类型
     * @return 操作是否成功
     */
    protected <E> boolean executeBatch(Collection<E> list, int batchSize, BiConsumer<SqlSession, E> consumer) {
        return SqlHelper.executeBatch(this.entityClass, this.log, list, batchSize, consumer);
    }

    /**
     * 执行批量操作,默认批量大小为 1000
     * @param list 要操作的对象集合
     * @param consumer 批量操作的消费者
     * @param <E> 对象集合的元素类型
     * @return 操作是否成功
     */
    protected <E> boolean executeBatch(Collection<E> list, BiConsumer<SqlSession, E> consumer) {
        return this.executeBatch(list, 1000, consumer);
    }

    /**
     * 根据 ID 删除实体对象
     * @param id 要删除的实体对象的 ID
     * @return 删除操作是否成功
     */
    public boolean removeById(Serializable id) {
        // 获取实体类的表信息
        TableInfo tableInfo = TableInfoHelper.getTableInfo(this.getEntityClass());
        // 如果存在逻辑删除且需要更新填充,则调用 removeById(id, true) 方法;否则直接调用 baseMapper 的 deleteById 方法
        return tableInfo.isWithLogicDelete() && tableInfo.isWithUpdateFill() ? this.removeById(id, true) : SqlHelper.retBool(this.getBaseMapper().deleteById(id));
    }

    /**
     * 根据 ID 列表批量删除实体对象
     * @param list 要删除的实体对象的 ID 列表
     * @return 删除操作是否成功
     */
    @Transactional(rollbackFor = {Exception.class})
    public boolean removeByIds(Collection<?> list) {
        // 如果 ID 列表为空,直接返回 false
        if (CollectionUtils.isEmpty(list)) {
            return false;
        } else {
            // 获取实体类的表信息
            TableInfo tableInfo = TableInfoHelper.getTableInfo(this.getEntityClass());
            // 如果存在逻辑删除且需要更新填充,则调用 removeBatchByIds(list, true) 方法;否则直接调用 baseMapper 的 deleteBatchIds 方法
            return tableInfo.isWithLogicDelete() && tableInfo.isWithUpdateFill() ? this.removeBatchByIds(list, true) : SqlHelper.retBool(this.getBaseMapper().deleteBatchIds(list));
        }
    }

    /**
     * 根据 ID 删除实体对象,支持更新填充
     * @param id 要删除的实体对象的 ID
     * @param useFill 是否使用更新填充
     * @return 删除操作是否成功
     */
    public boolean removeById(Serializable id, boolean useFill) {
        // 获取实体类的表信息
        TableInfo tableInfo = TableInfoHelper.getTableInfo(this.entityClass);
        if (useFill && tableInfo.isWithLogicDelete() && !this.entityClass.isAssignableFrom(id.getClass())) {
            // 创建实体类的实例
            T instance = tableInfo.newInstance();
            // 设置实体对象的主键值
            tableInfo.setPropertyValue(instance, tableInfo.getKeyProperty(), new Object[]{id});
            // 递归调用 removeById 方法
            return this.removeById(instance);
        } else {
            // 直接调用 baseMapper 的 deleteById 方法
            return SqlHelper.retBool(this.getBaseMapper().deleteById(id));
        }
    }

    /**
     * 根据 ID 列表批量删除实体对象,指定批量大小
     * @param list 要删除的实体对象的 ID 列表
     * @param batchSize 批量操作的大小
     * @return 删除操作是否成功
     */
    @Transactional(rollbackFor = {Exception.class})
    public boolean removeBatchByIds(Collection<?> list, int batchSize) {
        // 获取实体类的表信息
        TableInfo tableInfo = TableInfoHelper.getTableInfo(this.entityClass);
        // 调用 removeBatchByIds 方法,传入批量大小和是否使用更新填充的标志
        return this.removeBatchByIds(list, batchSize, tableInfo.isWithLogicDelete() && tableInfo.isWithUpdateFill());
    }

    /**
     * 根据 ID 列表批量删除实体对象,指定批量大小和是否使用更新填充
     * @param list 要删除的实体对象的 ID 列表
     * @param batchSize 批量操作的大小
     * @param useFill 是否使用更新填充
     * @return 删除操作是否成功
     */
    @Transactional(rollbackFor = {Exception.class})
    public boolean removeBatchByIds(Collection<?> list, int batchSize, boolean useFill) {
        // 获取根据 ID 删除记录的 SQL 语句
        String sqlStatement = this.getSqlStatement(SqlMethod.DELETE_BY_ID);
        // 获取实体类的表信息
        TableInfo tableInfo = TableInfoHelper.getTableInfo(this.entityClass);
        // 执行批量删除操作
        return this.executeBatch(list, batchSize, (sqlSession, e) -> {
            if (useFill && tableInfo.isWithLogicDelete()) {
                if (this.entityClass.isAssignableFrom(e.getClass())) {
                    // 直接执行更新操作
                    sqlSession.update(sqlStatement, e);
                } else {
                    // 创建实体类的实例
                    T instance = tableInfo.newInstance();
                    // 设置实体对象的主键值
                    tableInfo.setPropertyValue(instance, tableInfo.getKeyProperty(), new Object[]{e});
                    // 执行更新操作
                    sqlSession.update(sqlStatement, instance);
                }
            } else {
                // 直接执行更新操作
                sqlSession.update(sqlStatement, e);
            }
        });
    }
}

 

        使用 protected 可以将访问权限限制在类的继承体系和同一个包内,避免外部类不恰当的调用。

        在 ServiceImpl 类作为基础服务实现类的情况下,可能会有多个子类继承它,子类可以直接使用或重写这些 protected 成员,以此实现特定的业务逻辑。


3.创建Service接口和实现类


/**
 * UserService继承IService模板提供的基础功能
 */
public interface UserService extends IService<User>{
}

实现类:

/**
 * ServiceImpl实现了IService,提供了IService中基础功能的实现
 * 若ServiceImpl无法满足业务需求,则可以使用自定的UserService定义方法,并在实现类中实现 */

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper,User> implements UserService{
}

 

@Autowired
private UserService userService;

 

        这个不报错因为有他的实现类,其实创建的是它实现类的对象。(且只有一个实现类)

        @Autowired 注解应用于 UserService 类型的字段时,Spring 容器会在自身的组件池中查找实现了 UserService 接口的类。一旦找到对应的实现类,Spring 容器就会创建该实现类的实例,然后把这个实例注入到 userService 字段中。

        如果有两个实现类,就需要指定实现类名称了。

AutoWired和Resource之间区别

        一个是java提供的,通过反射

        一个是spring框架提供的,


4. 测试

4.1 插入

1> 插入单个实体类

原码:

 /**
     * 保存单个实体对象到数据库
     * @param entity 要保存的实体对象
     * @return 保存操作是否成功的布尔值
     */
    default boolean save(T entity) {
        // 调用基础映射器的 insert 方法插入实体对象,并通过 SqlHelper 将结果转换为布尔值
        return SqlHelper.retBool(this.getBaseMapper().insert(entity));
    }

2> 批量保存,使用默认批量大小

原码:

 /**
     * 批量保存实体对象到数据库,使用默认批量大小
     * @param entityList 要保存的实体对象集合
     * @return 批量保存操作是否成功的布尔值
     */
    @Transactional(
        rollbackFor = {Exception.class}
    )
    default boolean saveBatch(Collection<T> entityList) {
        // 调用带批量大小参数的 saveBatch 方法,使用默认批量大小 1000
        return this.saveBatch(entityList, 1000);
    }

测试:

/***
 *批量插入,使用默认批量大小
 */
@Test
public void testSaveBatch(){
   // SQL长度有限制,海量数据插入单条SQL无法实行,
   // 因此MP将批量插入放在了通用Service中实现,而不是通用Mapper
   ArrayList<User> users = new ArrayList<>();
   for (int i = 0; i < 5; i++) {
      User user = new User();
      user.setName("szy" + i);
      user.setAge(20 + i);
      users.add(user);
   }
   //SQL:INSERT INTO t_user ( username, age ) VALUES ( ?, ? )
   userService.saveBatch(users);
}

        在saveBatch方法中,默认的批量大小被设置为1000,即如果不指定其他批量大小,默认会将集合中的数据按照每1000条为一批进行插入操作。

        使用批量插入的好处是可以减少与数据库的交互次数,提高数据插入的效率。

        如果没有批量大小的概念,每插入一条数据都需要与数据库进行一次交互,当数据量较大时,会消耗大量的时间在数据库连接和交互上。

        而通过批量插入,将多条数据打包在一起发送到数据库执行,可以显著减少数据库连接的开销,提高插入数据的性能。

3> 批量保存,指定批量大小

原码:

/**
     * 批量保存实体对象到数据库,指定批量大小
     * @param var1 要保存的实体对象集合
     * @param var2 批量大小
     * @return 批量保存操作是否成功的布尔值
     */
    boolean saveBatch(Collection<T> var1, int var2);

测试:

@Test
public void testSaveBatchVar(){
   ArrayList<User> users = new ArrayList<>();
   for (int i = 5; i < 10; i++) {
      User user = new User();
      user.setName("szy" + i);
      user.setAge(20 + i);
      users.add(user);
   }
   //SQL:INSERT INTO t_user ( username, age ) VALUES ( ?, ? )
   userService.saveBatch(users,100);
}

 

4> 批量保存或更新,使用默认批量大小

原码:

 /**
     * 批量保存或更新实体对象到数据库,使用默认批量大小
     * @param entityList 要保存或更新的实体对象集合
     * @return 批量保存或更新操作是否成功的布尔值
     */
    @Transactional(
        rollbackFor = {Exception.class}
    )
    default boolean saveOrUpdateBatch(Collection<T> entityList) {
        // 调用带批量大小参数的 saveOrUpdateBatch 方法,使用默认批量大小 1000
        return this.saveOrUpdateBatch(entityList, 1000);
    }

测试:

/***
 * 批量保存或更新,使用默认批量大小
 */
@Test
public void testSaveOrUpdateBatch(){
   List<User> list=new ArrayList<>();
   User user1=new User();
   user1.setId(1L);
   user1.setName("admin");
   list.add(user1);//修改

   User user2=new User();
   user2.setName("harriet");
   user2.setAge(21);
   user2.setEmail("@qq.com");
   list.add(user2);//添加
   System.out.println(userService.saveOrUpdateBatch(list));
}

 

 

5> 批量保存或更新,指定批量大小

原码:

  /**
     * 批量保存或更新实体对象到数据库,指定批量大小
     * @param var1 要保存或更新的实体对象集合
     * @param var2 批量大小
     * @return 批量保存或更新操作是否成功的布尔值
     */
    boolean saveOrUpdateBatch(Collection<T> var1, int var2);

测试:

/***
 * 批量保存或更新,指定批量大小
 */
@Test
public void testSaveOrUpdateBatch2(){
   List<User> list=new ArrayList<>();
   User user1=new User();
   user1.setId(4L);
   user1.setName("admin");
   list.add(user1);//修改

   User user2=new User();
   user2.setName("rain");
   user2.setAge(21);
   user2.setEmail("@qq.com");
   list.add(user2);//添加
   System.out.println(userService.saveOrUpdateBatch(list,100));
}

 

4.2 删除

1> 根据实体对象ID删除

原码:

 /**
     * 根据实体对象的 ID 删除该对象
     * @param id 要删除的实体对象的 ID
     * @return 删除操作是否成功的布尔值
     */
    default boolean removeById(Serializable id) {
        // 调用基础映射器的 deleteById 方法删除对象,并通过 SqlHelper 将结果转换为布尔值
        return SqlHelper.retBool(this.getBaseMapper().deleteById(id));
    }

测试:

/***
 * 不支持使用填充的根据ID删除
 */

@Test
public void testRemoveByIdNo(){
   System.out.println(userService.removeById(1903761913798144004L));
}

 

 

2> 根据实体对象ID删除,支持使用填充

原码:

 /**
     * 根据实体对象的 ID 删除该对象,支持使用填充(可能是逻辑删除时的字段填充)
     * @param id 要删除的实体对象的 ID
     * @param useFill 是否使用填充
     * @return 删除操作是否成功的布尔值
     * @throws UnsupportedOperationException 默认抛出此异常,需实现类重写
     */
    default boolean removeById(Serializable id, boolean useFill) {
        throw new UnsupportedOperationException("不支持的方法!");
    }
在数据库操作中,删除数据通常有两种方式:
  • 物理删除:直接从数据库里把对应的记录删掉,这会让数据在数据库中彻底消失。
  • 逻辑删除:不真正删除数据库里的记录,而是借助修改特定字段(例如 is_deleted)的值来标记该记录已被删除。后续查询时,通过过滤该字段的值,来确保查询结果不包含已标记为删除的记录。
        “支持使用填充” 的删除方法主要用于实现逻辑删除,通过填充逻辑删除字段的值,在不真正删除数据的情况下,标记记录为已删除。这样做的好处是可以保留历史数据,便于后续的数据分析与审计。
测试:
/***
 * 支持使用填充的根据ID删除
 */
@Test
public void testRemoveById(){
   System.out.println(userService.removeById(1903761913798144005L,true));
}

 

 

3> 根据实体对象删除

原码:


    /**
     * 根据实体对象删除该对象
     * @param entity 要删除的实体对象
     * @return 删除操作是否成功的布尔值
     */
    default boolean removeById(T entity) {
        // 调用基础映射器的 deleteById 方法删除对象,并通过 SqlHelper 将结果转换为布尔值
        return SqlHelper.retBool(this.getBaseMapper().deleteById(entity));
    }

测试:

@Test
public void testRemoveByEntity(){
   User user=new User();
   user.setAge(26);
   System.out.println(userService.removeById(user));
}

         从这可看出,支持的是实体类,给ID赋值的。

/***
 * 根据实体对象删除
 */
@Test
public void testRemoveByEntity(){
   User user=new User();
   user.setId(1903761913798144002L);
   System.out.println(userService.removeById(user));
}

4>  根据columnMap删除

原码:

 /**
     * 根据条件映射删除实体对象
     * @param columnMap 条件映射,包含列名和对应的值
     * @return 删除操作是否成功的布尔值
     */
    default boolean removeByMap(Map<String, Object> columnMap) {
        // 确保条件映射不为空
        Assert.notEmpty(columnMap, "error: columnMap must not be empty", new Object[0]);
        // 调用基础映射器的 deleteByMap 方法删除对象,并通过 SqlHelper 将结果转换为布尔值
        return SqlHelper.retBool(this.getBaseMapper().deleteByMap(columnMap));
    }

测试:

/***
 * 根据columnMap删除
 */
@Test
public void testRemoveByMap(){
   Map<String,Object> map=new HashMap<>();
   map.put("name","szy7");
   map.put("age",27);
   System.out.println(userService.removeByMap(map));
}

5>  根据查询条件包装器queryWrapper删除

原码:

 /**
     * 根据查询条件包装器删除实体对象
     * @param queryWrapper 查询条件包装器
     * @return 删除操作是否成功的布尔值
     */
    default boolean remove(Wrapper<T> queryWrapper) {
        // 调用基础映射器的 delete 方法删除对象,并通过 SqlHelper 将结果转换为布尔值
        return SqlHelper.retBool(this.getBaseMapper().delete(queryWrapper));
    }

6> 根据ID列表批量删除

原码:

/**
     * 根据 ID 列表批量删除实体对象
     * @param list 要删除的实体对象的 ID 列表
     * @return 删除操作是否成功的布尔值
     */
    default boolean removeByIds(Collection<?> list) {
        // 如果 ID 列表为空,返回 false;否则调用基础映射器的 deleteBatchIds 方法删除对象,并通过 SqlHelper 将结果转换为布尔值
        return CollectionUtils.isEmpty(list) ? false : SqlHelper.retBool(this.getBaseMapper().deleteBatchIds(list));
    }

测试:

/***
 * 根据ID列表删除
 */

@Test
public void testRemoveByIds(){
   List<Long> list=Arrays.asList(1903742354500239363L,1903742354500239364L,1903761913701675009L);
   System.out.println(userService.removeBatchByIds(list));
}

 

7>  根据ID列表批量删除,支持使用填充

原码:

 /**
     * 根据 ID 列表批量删除实体对象,支持使用填充(可能是逻辑删除时的字段填充)
     * @param list 要删除的实体对象的 ID 列表
     * @param useFill 是否使用填充
     * @return 删除操作是否成功的布尔值
     */
    @Transactional(
        rollbackFor = {Exception.class}
    )
    default boolean removeByIds(Collection<?> list, boolean useFill) {
        if (CollectionUtils.isEmpty(list)) {
            return false;
        } else {
            // 如果使用填充,调用 removeBatchByIds 方法并传入 true;否则调用基础映射器的 deleteBatchIds 方法删除对象,并通过 SqlHelper 将结果转换为布尔值
            return useFill ? this.removeBatchByIds(list, true) : SqlHelper.retBool(this.getBaseMapper().deleteBatchIds(list));
        }
    }

8> 根据ID列表批量删除,使用默认批量大小

原码:

 /**
     * 根据 ID 列表批量删除实体对象,使用默认批量大小
     * @param list 要删除的实体对象的 ID 列表
     * @return 删除操作是否成功的布尔值
     */
    @Transactional(
        rollbackFor = {Exception.class}
    )
    default boolean removeBatchByIds(Collection<?> list) {
        // 调用带批量大小和填充标志参数的 removeBatchByIds 方法,使用默认批量大小 1000
        return this.removeBatchByIds(list, 1000);
    }

9> 根据ID列表批量删除,使用默认批量大小并使用填充

原码:

 /**
     * 根据 ID 列表批量删除实体对象,使用默认批量大小并指定是否使用填充
     * @param list 要删除的实体对象的 ID 列表
     * @param useFill 是否使用填充
     * @return 删除操作是否成功的布尔值
     */
    @Transactional(
        rollbackFor = {Exception.class}
    )
    default boolean removeBatchByIds(Collection<?> list, boolean useFill) {
        // 调用带批量大小和填充标志参数的 removeBatchByIds 方法,使用默认批量大小 1000
        return this.removeBatchByIds(list, 1000, useFill);
    }

10> 根据ID列表批量删除,指定批量大小

原码:

/**
     * 根据 ID 列表批量删除实体对象,指定批量大小
     * @param list 要删除的实体对象的 ID 列表
     * @param batchSize 批量大小
     * @return 删除操作是否成功的布尔值
     * @throws UnsupportedOperationException 默认抛出此异常,需实现类重写
     */
    default boolean removeBatchByIds(Collection<?> list, int batchSize) {
        throw new UnsupportedOperationException("不支持的方法!");
    }

11> 根据ID列表批量删除,指定批量大小和是否使用填充

原码:

 /**
     * 根据 ID 列表批量删除实体对象,指定批量大小和是否使用填充
     * @param list 要删除的实体对象的 ID 列表
     * @param batchSize 批量大小
     * @param useFill 是否使用填充
     * @return 删除操作是否成功的布尔值
     * @throws UnsupportedOperationException 默认抛出此异常,需实现类重写
     */
    default boolean removeBatchByIds(Collection<?> list, int batchSize, boolean useFill) {
        throw new UnsupportedOperationException("不支持的方法!");
    }

4.3 修改

1> 根据ID修改

原码:

 /**
     * 根据实体对象的 ID 更新该对象
     * @param entity 要更新的实体对象
     * @return 更新操作是否成功的布尔值
     */
    default boolean updateById(T entity) {
        // 调用基础映射器的 updateById 方法更新对象,并通过 SqlHelper 将结果转换为布尔值
        return SqlHelper.retBool(this.getBaseMapper().updateById(entity));
    }

测试:

/***
 * 根据ID修改
 */
@Test
public void testUpdateById2(){
   User user=new User();
   user.setId(1903742354500239361L);
   user.setEmail("111@qq.com");
   System.out.println(userService.updateById(user));
}

2>  根据修改条件包装器修改

原码:

 /**
     * 根据更新条件包装器更新实体对象
     * @param updateWrapper 更新条件包装器
     * @return 更新操作是否成功的布尔值
     */
    default boolean update(Wrapper<T> updateWrapper) {
        // 调用带实体对象和更新条件包装器参数的 update 方法,传入 null 作为实体对象
        return this.update((Object)null, updateWrapper);
    }

测试:


/***
 * 使用修改条件包装器
 */
@Test
public void testUpdate(){
   UpdateWrapper<User> updateWrapper=new UpdateWrapper<>();
   // 设置更新条件,例如更新年龄大于 20 的用户的姓名为 "Updated Name"
   updateWrapper.set("name", "Updated Name")
         .gt("age", 20);
   // 调用 update 方法
   System.out.println(userService.update(updateWrapper));

}

 

3>  根据实体对象和修改条件包装器修改

原码:

 /**
     * 根据实体对象和更新条件包装器更新实体对象
     * @param entity 要更新的实体对象
     * @param updateWrapper 更新条件包装器
     * @return 更新操作是否成功的布尔值
     */
    default boolean update(T entity, Wrapper<T> updateWrapper) {
        // 调用基础映射器的 update 方法更新对象,并通过 SqlHelper 将结果转换为布尔值
        return SqlHelper.retBool(this.getBaseMapper().update(entity, updateWrapper));
    }

测试:

/***
 * 根据实体对象和修改条件包装器修改
 */
@Test
public void testUpdate2(){
   User user=new User();
   user.setName("hhhhh");

   User user2=new User();
   user2.setName("szy0");
   UpdateWrapper<User> updateWrapper=new UpdateWrapper<>(user2);
   System.out.println(userService.update(user,updateWrapper));
}

 4> 根据ID批量修改,使用默认批量大小

原码:

/**
     * 根据 ID 批量更新实体对象,使用默认批量大小
     * @param entityList 要更新的实体对象集合
     * @return 批量更新操作是否成功的布尔值
     */
    @Transactional(
        rollbackFor = {Exception.class}
    )
    default boolean updateBatchById(Collection<T> entityList) {
        // 调用带批量大小参数的 updateBatchById 方法,使用默认批量大小 1000
        return this.updateBatchById(entityList, 1000);
    }

5> 根据ID批量修改,指定批量大小

原码:

/**
     * 根据 ID 批量更新实体对象,指定批量大小
     * @param var1 要更新的实体对象集合
     * @param var2 批量大小
     * @return 批量更新操作是否成功的布尔值
     */
    boolean updateBatchById(Collection<T> var1, int var2);

6> 保存或更新单个实体对象

原码:

    /**
     * 保存或更新单个实体对象
     * @param var1 要保存或更新的实体对象
     * @return 保存或更新操作是否成功的布尔值
     */
    boolean saveOrUpdate(T var1);

4.4 查询

1> 根据实体对象的ID获取该对象

原码:

 /**
     * 根据实体对象的 ID 获取该对象
     * @param id 要获取的实体对象的 ID
     * @return 获取到的实体对象
     */
    default T getById(Serializable id) {
        // 调用基础映射器的 selectById 方法获取对象
        return this.getBaseMapper().selectById(id);
    }

2> 根据ID列表获取实体对象列表

原码:

/**
     * 根据 ID 列表获取实体对象列表
     * @param idList 要获取的实体对象的 ID 列表
     * @return 获取到的实体对象列表
     */
    default List<T> listByIds(Collection<? extends Serializable> idList) {
        // 调用基础映射器的 selectBatchIds 方法获取对象列表
        return this.getBaseMapper().selectBatchIds(idList);
    }

3> 根据条件映射获取实体对象列表

原码:

 /**
     * 根据条件映射获取实体对象列表
     * @param columnMap 条件映射,包含列名和对应的值
     * @return 获取到的实体对象列表
     */
    default List<T> listByMap(Map<String, Object> columnMap) {
        // 调用基础映射器的 selectByMap 方法获取对象列表
        return this.getBaseMapper().selectByMap(columnMap);
    }

4> 根据查询条件包装器获取单个实体对象,默认抛出异常时返回对象

原码:

 /**
     * 根据查询条件包装器获取单个实体对象,默认抛出异常时返回对象
     * @param queryWrapper 查询条件包装器
     * @return 获取到的单个实体对象
     */
    default T getOne(Wrapper<T> queryWrapper) {
        // 调用带抛出异常标志参数的 getOne 方法,传入 true 表示抛出异常时返回对象
        return this.getOne(queryWrapper, true);
    }

测试:

/***
 * 根据查询条件包装器获取单个实体对象,默认抛出异常时返回对象
 */
@Test
public void testGetOne(){
   QueryWrapper<User> queryWrapper=new QueryWrapper<>();
   queryWrapper.eq("name","harriet");
   User user=userService.getOne(queryWrapper);
   System.out.println(user);
}

5>  根据查询条件包装器获取单个实体对象,指定是否抛出异常

原码:

 /**
     * 根据查询条件包装器获取单个实体对象,指定是否抛出异常
     * @param var1 查询条件包装器
     * @param var2 是否抛出异常的标志
     * @return 获取到的单个实体对象
     */
    T getOne(Wrapper<T> var1, boolean var2);

6> 根据查询条件包装器获取单个结果的Map表示

原码:

  /**
     * 根据查询条件包装器获取单个结果的 Map 表示
     * @param var1 查询条件包装器
     * @return 获取到的单个结果的 Map 表示
     */
    Map<String, Object> getMap(Wrapper<T> var1);

7> 根据查询条件包装器获取单个结果,并通过Function进行转换

原码:

  /**
     * 根据查询条件包装器获取单个结果,并通过 Function 进行转换
     * @param var1 查询条件包装器
     * @param var2 转换函数
     * @param <V> 转换后的类型
     * @return 转换后的单个结果
     */
    <V> V getObj(Wrapper<T> var1, Function<? super Object, V> var2);

8> 统计总数

原码:

 /**
     * 获取实体对象的总数,使用空的查询条件包装器
     * @return 实体对象的总数
     */
    default long count() {
        // 调用带查询条件包装器参数的 count 方法,传入空的查询条件包装器
        return this.count(Wrappers.emptyWrapper());
    }

测试:

/***
 * 统计数量
 */
@Test
public void testGetCount(){
   long count = userService.count();
   System.out.println("总记录数:" + count);
}

9> 剩下的一些(查总数,添加分页,转换函数,链式包装器):

 /**
     * 根据查询条件包装器获取实体对象的总数
     * @param queryWrapper 查询条件包装器
     * @return 实体对象的总数
     */
    default long count(Wrapper<T> queryWrapper) {
        // 调用基础映射器的 selectCount 方法获取总数,并通过 SqlHelper 进行结果处理
        return SqlHelper.retCount(this.getBaseMapper().selectCount(queryWrapper));
    }

    /**
     * 根据查询条件包装器获取实体对象列表
     * @param queryWrapper 查询条件包装器
     * @return 获取到的实体对象列表
     */
    default List<T> list(Wrapper<T> queryWrapper) {
        // 调用基础映射器的 selectList 方法获取对象列表
        return this.getBaseMapper().selectList(queryWrapper);
    }

    /**
     * 获取所有实体对象列表,使用空的查询条件包装器
     * @return 获取到的所有实体对象列表
     */
    default List<T> list() {
        // 调用带查询条件包装器参数的 list 方法,传入空的查询条件包装器
        return this.list(Wrappers.emptyWrapper());
    }

    /**
     * 根据分页对象和查询条件包装器进行分页查询
     * @param page 分页对象
     * @param queryWrapper 查询条件包装器
     * @param <E> 分页对象的类型
     * @return 分页查询结果
     */
    default <E extends IPage<T>> E page(E page, Wrapper<T> queryWrapper) {
        // 调用基础映射器的 selectPage 方法进行分页查询
        return this.getBaseMapper().selectPage(page, queryWrapper);
    }

    /**
     * 根据分页对象进行分页查询,使用空的查询条件包装器
     * @param page 分页对象
     * @param <E> 分页对象的类型
     * @return 分页查询结果
     */
    default <E extends IPage<T>> E page(E page) {
        // 调用带分页对象和查询条件包装器参数的 page 方法,传入空的查询条件包装器
        return this.page(page, Wrappers.emptyWrapper());
    }

    /**
     * 根据查询条件包装器获取结果的 Map 列表
     * @param queryWrapper 查询条件包装器
     * @return 获取到的结果的 Map 列表
     */
    default List<Map<String, Object>> listMaps(Wrapper<T> queryWrapper) {
        // 调用基础映射器的 selectMaps 方法获取结果的 Map 列表
        return this.getBaseMapper().selectMaps(queryWrapper);
    }

    /**
     * 获取所有结果的 Map 列表,使用空的查询条件包装器
     * @return 获取到的所有结果的 Map 列表
     */
    default List<Map<String, Object>> listMaps() {
        // 调用带查询条件包装器参数的 listMaps 方法,传入空的查询条件包装器
        return this.listMaps(Wrappers.emptyWrapper());
    }

    /**
     * 获取所有结果的对象列表,使用默认的转换函数
     * @return 获取到的所有结果的对象列表
     */
    default List<Object> listObjs() {
        // 调用带转换函数参数的 listObjs 方法,传入默认的转换函数
        return this.listObjs(Function.identity());
    }

    /**
     * 根据转换函数获取结果的对象列表,使用空的查询条件包装器
     * @param mapper 转换函数
     * @param <V> 转换后的类型
     * @return 获取到的结果的对象列表
     */
    default <V> List<V> listObjs(Function<? super Object, V> mapper) {
        // 调用带查询条件包装器和转换函数参数的 listObjs 方法,传入空的查询条件包装器
        return this.listObjs(Wrappers.emptyWrapper(), mapper);
    }

    /**
     * 根据查询条件包装器获取结果的对象列表,使用默认的转换函数
     * @param queryWrapper 查询条件包装器
     * @return 获取到的结果的对象列表
     */
    default List<Object> listObjs(Wrapper<T> queryWrapper) {
        // 调用带查询条件包装器和转换函数参数的 listObjs 方法,传入默认的转换函数
        return this.listObjs(queryWrapper, Function.identity());
    }

    /**
     * 根据查询条件包装器和转换函数获取结果的对象列表
     * @param queryWrapper 查询条件包装器
     * @param mapper 转换函数
     * @param <V> 转换后的类型
     * @return 获取到的结果的对象列表
     */
    default <V> List<V> listObjs(Wrapper<T> queryWrapper, Function<? super Object, V> mapper) {
        // 调用基础映射器的 selectObjs 方法获取结果列表,过滤掉 null 值,通过转换函数进行转换,最后收集为列表
        return (List)this.getBaseMapper().selectObjs(queryWrapper).stream().filter(Objects::nonNull).map(mapper).collect(Collectors.toList());
    }

    /**
     * 根据分页对象和查询条件包装器进行分页查询,返回结果的 Map 分页对象
     * @param page 分页对象
     * @param queryWrapper 查询条件包装器
     * @param <E> 分页对象的类型
     * @return 分页查询结果的 Map 分页对象
     */
    default <E extends IPage<Map<String, Object>>> E pageMaps(E page, Wrapper<T> queryWrapper) {
        // 调用基础映射器的 selectMapsPage 方法进行分页查询
        return this.getBaseMapper().selectMapsPage(page, queryWrapper);
    }

    /**
     * 根据分页对象进行分页查询,使用空的查询条件包装器,返回结果的 Map 分页对象
     * @param page 分页对象
     * @param <E> 分页对象的类型
     * @return 分页查询结果的 Map 分页对象
     */
    default <E extends IPage<Map<String, Object>>> E pageMaps(E page) {
        // 调用带分页对象和查询条件包装器参数的 pageMaps 方法,传入空的查询条件包装器
        return this.pageMaps(page, Wrappers.emptyWrapper());
    }

    /**
     * 获取基础的 Mapper 对象
     * @return 基础的 Mapper 对象
     */
    BaseMapper<T> getBaseMapper();

    /**
     * 获取实体类的 Class 对象
     * @return 实体类的 Class 对象
     */
    Class<T> getEntityClass();

    /**
     * 获取查询链式包装器
     * @return 查询链式包装器
     */
    default QueryChainWrapper<T> query() {
        // 调用 ChainWrappers 的 queryChain 方法获取查询链式包装器
        return ChainWrappers.queryChain(this.getBaseMapper());
    }

    /**
     * 获取 Lambda 查询链式包装器
     * @return Lambda 查询链式包装器
     */
    default LambdaQueryChainWrapper<T> lambdaQuery() {
        // 调用 ChainWrappers 的 lambdaQueryChain 方法获取 Lambda 查询链式包装器
        return ChainWrappers.lambdaQueryChain(this.getBaseMapper());
    }

    /**
     * 获取 Kt 查询链式包装器
     * @return Kt 查询链式包装器
     */
    default KtQueryChainWrapper<T> ktQuery() {
        // 调用 ChainWrappers 的 ktQueryChain 方法获取 Kt 查询链式包装器
        return ChainWrappers.ktQueryChain(this.getBaseMapper(), this.getEntityClass());
    }

    /**
     * 获取 Kt 更新链式包装器
     * @return Kt 更新链式包装器
     */
    default KtUpdateChainWrapper<T> ktUpdate() {
        // 调用 ChainWrappers 的 ktUpdateChain 方法获取 Kt 更新链式包装器
        return ChainWrappers.ktUpdateChain(this.getBaseMapper(), this.getEntityClass());
    }

    /**
     * 获取更新链式包装器
     * @return 更新链式包装器
     */
    default UpdateChainWrapper<T> update() {
        // 调用 ChainWrappers 的 updateChain 方法获取更新链式包装器
        return ChainWrappers.updateChain(this.getBaseMapper());
    }

    /**
     * 获取 Lambda 更新链式包装器
     * @return Lambda 更新链式包装器
     */
    default LambdaUpdateChainWrapper<T> lambdaUpdate() {
        // 调用 ChainWrappers 的 lambdaUpdateChain 方法获取 Lambda 更新链式包装器
        return ChainWrappers.lambdaUpdateChain(this.getBaseMapper());
    }

    /**
     * 根据实体对象和更新条件包装器保存或更新实体对象
     * @param entity 要保存或更新的实体对象
     * @param updateWrapper 更新条件包装器
     * @return 保存或更新操作是否成功的布尔值
     */
    default boolean saveOrUpdate(T entity, Wrapper<T> updateWrapper) {
        // 先尝试更新操作,如果更新失败则尝试保存或更新操作
        return this.update(entity, updateWrapper) || this.saveOrUpdate(entity);
    }

相关文章:

  • 决策树基础
  • 代码随想录算法训练营第38天 | 322. 零钱兑换 279.完全平方数 139.单词拆分 背包问题总结
  • “跨越时代的技术进步:CPU缓存如何塑造了智能手机和智能家居的未来?
  • 【2025】基于ssm+jsp的二手商城系统设计与实现(源码、万字文档、图文修改、调试答疑)
  • go-zero学习笔记
  • 第39章:CSI插件开发与定制化存储需求
  • Django框架视图与路由(一)
  • 我的Go学习路线概览
  • 关于 URH(Universal Radio Hacker) 的详细介绍、安装指南、配置方法及使用说明
  • Java 的 AutoCloseable 接口
  • 警翼(Pe)执法记录仪格式化后的恢复方法
  • 分类预测 | Matlab实现BO-GRU-Attention贝叶斯优化门控循环单元融合注意力机制多特征分类预测
  • 【系统稳定性】1.13 解析gcore
  • 京东一面:MySQL 主备延迟有哪些坑?主备切换策略
  • 【AI模型】深度解析:DeepSeek的联网搜索的实现原理与认知误区
  • 运功学-【机械臂】
  • 1.设备电气设计、装配的注意事项
  • C语言入门教程100讲(19)do-while 循环
  • 动态规划完全背包系列一>完全平方数
  • android......
  • 北部艳阳高照、南部下冰雹,五一长假首日上海天气很“热闹”
  • 印度宣布即日起对所有巴基斯坦航班关闭领空
  • 深入贯彻中央八项规定精神学习教育中央指导组派驻地方和单位名单公布
  • 外交部:欢迎外国朋友“五一”来中国
  • 上海第三家“胖永辉”在浦东开业,设立了外贸产品专区
  • 人民日报头版:上海纵深推进浦东高水平改革开放