JeecgBoot 3.6.1中MyBatisPlus IService接口深度解析与应用场景实战

JeecgBoot 3.6.1中MyBatisPlus IService接口深度解析与应用场景实战


我们以下示例解析与应用场景以User为例,假设我们有一个User实体类,包含id(主键)、username(用户名)、password(密码)等属性,并且已经在MyBatis-Plus中配置了相关映射关系

一、插入一条记录(选择字段,策略插入)

1、接口代码示例

    /**
     * 默认批次提交数量
     */
    int DEFAULT_BATCH_SIZE = 1000;

    /**
     * 插入一条记录(选择字段,策略插入)
     *
     * @param entity 实体对象
     */
    default boolean save(T entity) {
        return SqlHelper.retBool(getBaseMapper().insert(entity));
    }

2、变量解释

DEFAULT_BATCH_SIZE:这是默认的批量处理数据的数量,例如在进行批量插入、更新等操作时,如果未指定批次大小,则会使用这个默认值,下面的代码中出现此变量则对此不作赘述。

3、方法解析

这个方法是针对泛型T(这里的T为User)的一个插入方法。在具体应用中,当你有一个User对象需要持久化到数据库时,可以直接调用此方法。
getBaseMapper():这是MyBatis-Plus中的一个方法,用于获取当前实体类(如User)对应的通用Mapper接口,该接口提供了基本的CRUD操作。
insert(entity):在获取到的BaseMapper中调用insert方法,将传入的User对象插入到数据库中。由于是“策略插入”,框架会根据User类的注解信息(如@TableField注解标记的主键策略等)智能决定插入方式。

4、应用场景实战

User user = new User();
user.setUsername("testUser");
user.setPassword("testPassword");

// 调用save方法插入新用户
boolean isSuccess = userService.save(user);

在这段代码中,userService是一个注入了UserMapper接口的对象,而UserMapper继承自BaseMapper,因此可以调用save方法。通过这个方法,我们就能便捷地将一个新创建的User对象插入到数据库中,无需关心具体的SQL语句编写和执行。同时,SqlHelper.retBool会对执行结果进行处理,返回一个布尔值表示插入是否成功。

二、插入(批量)

1、接口示例代码

    /**
     * 插入(批量)
     *
     * @param entityList 实体对象集合
     */
    @Transactional(rollbackFor = Exception.class)
    default boolean saveBatch(Collection<T> entityList) {
        return saveBatch(entityList, DEFAULT_BATCH_SIZE);
    }

    /**
     * 插入(批量)
     *
     * @param entityList 实体对象集合
     * @param batchSize  插入批次数量
     */
    boolean saveBatch(Collection<T> entityList, int batchSize);

2、方法解析

方法一:

@Transactional(rollbackFor = Exception.class)
default boolean saveBatch(Collection<T> entityList) {
    return saveBatch(entityList, DEFAULT_BATCH_SIZE);
}

此方法接收一个实体对象集合作为参数,它默认按照DEFAULT_BATCH_SIZE定义的批次大小进行插入。@Transactional注解表明该方法在一个事务中执行,如果在批量插入过程中发生任何异常,整个事务将会回滚,确保数据的一致性。如果插入过程中出现Exception异常,事务会自动回滚。

方法二:

boolean saveBatch(Collection<T> entityList, int batchSize);

这个方法同样接收一个实体对象集合作为参数,但多了一个batchSize参数,允许开发者自定义每个批次插入的数据量。当需要控制每次插入的数据量或者优化数据库性能时,可以使用这个方法。

3、应用场景实战

// 创建一组User对象
List<User> userList = new ArrayList<>();
for (int i = 0; i < 5000; i++) {
    User user = new User();
    user.setUsername("user" + i);
    user.setPassword("password");
    userList.add(user);
}

// 使用默认批次大小插入
boolean result1 = userService.saveBatch(userList);

// 或者,自定义批次大小插入
int customBatchSize = 500;
boolean result2 = userService.saveBatch(userList, customBatchSize);

在这段示例代码中,首先创建了5000个User对象,然后分别使用默认批次大小和自定义批次大小进行批量插入。这样能有效避免一次性执行大量SQL语句导致数据库压力过大,提高程序性能。

三、批量修改插入

1、接口示例代码

    /**
     * 批量修改插入
     *
     * @param entityList 实体对象集合
     */
    @Transactional(rollbackFor = Exception.class)
    default boolean saveOrUpdateBatch(Collection<T> entityList) {
        return saveOrUpdateBatch(entityList, DEFAULT_BATCH_SIZE);
    }

    /**
     * 批量修改插入
     *
     * @param entityList 实体对象集合
     * @param batchSize  每次的数量
     */
    boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize);

2、方法解析

这两个方法是针对批量修改或插入操作的实现,在MyBatis-Plus等ORM框架中常见,主要用于处理大批量数据时,既能够更新已存在记录,又能插入新记录的操作。

方法一:

@Transactional(rollbackFor = Exception.class)
default boolean saveOrUpdateBatch(Collection<T> entityList) {
    return saveOrUpdateBatch(entityList, DEFAULT_BATCH_SIZE);
}

此方法接收一个实体对象集合作为参数,并使用默认批次大小DEFAULT_BATCH_SIZE进行批量修改或插入操作。若实体对象集合中的某个对象在数据库中有对应的主键(即已存在的记录),则执行更新操作;若无对应主键记录,则执行插入操作。同时,整个方法被@Transactional注解包裹,意味着在遇到异常时会触发事务回滚,保证数据一致性。

方法二:

boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize);

此方法与第一个方法类似,不同之处在于允许开发者自定义批次大小。根据给定的batchSize参数,将实体对象集合按批处理,每批执行一定数量的修改或插入操作。

3、应用场景实战

// 创建一组User对象,其中部分已在数据库中存在(具有唯一标识符如ID)
List<User> userList = new ArrayList<>();
for (int i = 0; i < 5000; i++) {
    User user = new User();
    if (i % 2 == 0) { // 假设有偶数ID的用户已存在于数据库
        user.setId(i);
    }
    user.setUsername("user" + i);
    user.setPassword("password");
    userList.add(user);
}

// 使用默认批次大小进行批量修改或插入
boolean result1 = userService.saveOrUpdateBatch(userList);

// 或者,自定义批次大小进行批量修改或插入
int customBatchSize = 500;
boolean result2 = userService.saveOrUpdateBatch(userList, customBatchSize);

在这段示例代码中,创建了5000个User对象,其中一半(偶数ID)假设已经在数据库中存在。通过调用saveOrUpdateBatch方法,系统会根据实体对象中的ID判断是执行更新操作还是插入操作,从而实现批量修改或插入功能。同时,可以根据实际需求调整批次大小,优化数据库操作效率。

四、删除

1、接口示例代码

    /**
     * 根据 ID 删除
     *
     * @param id 主键ID
     */
    default boolean removeById(Serializable id) {
        return SqlHelper.retBool(getBaseMapper().deleteById(id));
    }

    /**
     * 根据 ID 删除
     *
     * @param id      主键(类型必须与实体类型字段保持一致)
     * @param useFill 是否启用填充(为true的情况,会将入参转换实体进行delete删除)
     * @return 删除结果
     * @since 3.5.0
     */
    default boolean removeById(Serializable id, boolean useFill) {
        throw new UnsupportedOperationException("不支持的方法!");
    }

    /**
     * 根据实体(ID)删除
     *
     * @param entity 实体
     * @since 3.4.4
     */
    default boolean removeById(T entity) {
        return SqlHelper.retBool(getBaseMapper().deleteById(entity));
    }

    /**
     * 根据 columnMap 条件,删除记录
     *
     * @param columnMap 表字段 map 对象
     */
    default boolean removeByMap(Map<String, Object> columnMap) {
        Assert.notEmpty(columnMap, "error: columnMap must not be empty");
        return SqlHelper.retBool(getBaseMapper().deleteByMap(columnMap));
    }

    /**
     * 根据 entity 条件,删除记录
     *
     * @param queryWrapper 实体包装类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
     */
    default boolean remove(Wrapper<T> queryWrapper) {
        return SqlHelper.retBool(getBaseMapper().delete(queryWrapper));
    }

    /**
     * 删除(根据ID 批量删除)
     *
     * @param list 主键ID或实体列表
     */
    default boolean removeByIds(Collection<?> list) {
        if (CollectionUtils.isEmpty(list)) {
            return false;
        }
        return SqlHelper.retBool(getBaseMapper().deleteBatchIds(list));
    }

    /**
     * 批量删除
     *
     * @param list    主键ID或实体列表
     * @param useFill 是否填充(为true的情况,会将入参转换实体进行delete删除)
     * @return 删除结果
     * @since 3.5.0
     */
    @Transactional(rollbackFor = Exception.class)
    default boolean removeByIds(Collection<?> list, boolean useFill) {
        if (CollectionUtils.isEmpty(list)) {
            return false;
        }
        if (useFill) {
            return removeBatchByIds(list, true);
        }
        return SqlHelper.retBool(getBaseMapper().deleteBatchIds(list));
    }

    /**
     * 批量删除(jdbc批量提交)
     *
     * @param list 主键ID或实体列表(主键ID类型必须与实体类型字段保持一致)
     * @return 删除结果
     * @since 3.5.0
     */
    @Transactional(rollbackFor = Exception.class)
    default boolean removeBatchByIds(Collection<?> list) {
        return removeBatchByIds(list, DEFAULT_BATCH_SIZE);
    }

    /**
     * 批量删除(jdbc批量提交)
     *
     * @param list    主键ID或实体列表(主键ID类型必须与实体类型字段保持一致)
     * @param useFill 是否启用填充(为true的情况,会将入参转换实体进行delete删除)
     * @return 删除结果
     * @since 3.5.0
     */
    @Transactional(rollbackFor = Exception.class)
    default boolean removeBatchByIds(Collection<?> list, boolean useFill) {
        return removeBatchByIds(list, DEFAULT_BATCH_SIZE, useFill);
    }

    /**
     * 批量删除(jdbc批量提交)
     *
     * @param list      主键ID或实体列表
     * @param batchSize 批次大小
     * @return 删除结果
     * @since 3.5.0
     */
    default boolean removeBatchByIds(Collection<?> list, int batchSize) {
        throw new UnsupportedOperationException("不支持的方法!");
    }

    /**
     * 批量删除(jdbc批量提交)
     *
     * @param list      主键ID或实体列表
     * @param batchSize 批次大小
     * @param useFill   是否启用填充(为true的情况,会将入参转换实体进行delete删除)
     * @return 删除结果
     * @since 3.5.0
     */
    default boolean removeBatchByIds(Collection<?> list, int batchSize, boolean useFill) {
        throw new UnsupportedOperationException("不支持的方法!");
    }

2、方法解析

这些方法是在MyBatis-Plus中定义的一系列删除操作,适用于不同的删除场景:

  1. removeById(Serializable id):根据主键ID删除单条记录。
  1. removeById(Serializable id, boolean useFill):根据主键ID删除单条记录,并且添加了一个useFill参数。如果为true,会将ID转换成实体对象再进行删除操作,不过此处抛出异常表示不支持该方法。
  1. removeById(T entity):根据实体对象的主键删除对应的记录,适用于已经拥有完整实体对象的情况。
  1. removeByMap(Map<String, Object> columnMap):根据提供的列名和对应的值的Map对象作为条件删除记录。
  1. remove(Wrapper queryWrapper):根据QueryWrapper封装的复杂查询条件删除满足条件的所有记录。
  1. removeByIds(Collection<?> list):批量删除,传入一个主键ID集合,一次性删除所有指定ID的记录。
  1. removeByIds(Collection<?> list, boolean useFill):同上,增加了useFill参数,用于控制是否将ID转换为实体对象进行删除。内部调用了removeBatchByIds方法,并根据useFill参数决定删除方式。
  1. removeBatchByIds(Collection<?> list) 和后续的重载方法:这些方法都是为了批量删除而设计的,它们接受一个主键ID或实体对象集合,并可以设定批次大小(batchSize)来分批提交删除操作以减少数据库压力。其中一些方法还提供了useFill参数,用来决定是否将ID转换为实体对象进行删除。不过最后两个重载方法目前并不支持,直接抛出了UnsupportedOperationException异常。

以上所有方法都利用了@Transactional注解来确保操作的原子性,即在遇到异常时能够进行事务回滚,保证数据的一致性。同时,SqlHelper.retBool方法用于处理并返回删除操作的结果,将其转化为布尔值表示删除是否成功。

3、应用场景实战

  1. 根据ID删除单条记录
// 假设我们要删除一个ID为1的用户
Long userId = 1L;
boolean isSuccess = userService.removeById(userId);
if (isSuccess) {
    System.out.println("用户删除成功");
} else {
    System.out.println("用户删除失败");
}
  1. 根据ID删除单条记录并启用填充功能
// 若有实现,可能是这样的用法
Long userId = 1L;
boolean isSuccess = userService.removeById(userId, true);
  1. 根据实体对象删除记录
// 假设我们有一个User实体对象user
User userToDelete = new User();
userToDelete.setId(2L);
boolean isSuccess = userService.removeById(userToDelete);
  1. 根据columnMap条件删除记录
Map<String, Object> columnMap = new HashMap<>();
columnMap.put("username", "testUser");
columnMap.put("status", "inactive");
boolean isSuccess = userService.removeByMap(columnMap);
  1. 根据entity条件删除记录
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("age", 18).and(i -> i.eq("gender", "male"));
boolean isSuccess = userService.remove(wrapper);
  1. 根据ID批量删除记录
List<Long> userIds = Arrays.asList(1L, 2L, 3L);
boolean isSuccess = userService.removeByIds(userIds);
  1. 批量删除并可以选择是否启用填充
List<Long> userIds = Arrays.asList(1L, 2L, 3L);
boolean isSuccess = userService.removeByIds(userIds, true); // 如果框架实现了此功能,可以启用填充
  1. 批量删除(jdbc批量提交)
List<Long> userIds = Arrays.asList(1L, 2L, 3L, ..., 1000L);
boolean isSuccess = userService.removeBatchByIds(userIds); // 自动按照默认批次大小删除
  1. 带有自定义批次大小和填充选项的批量删除
// 注意:以下两种方法在给出的代码中并未实现
List<Long> userIds = Arrays.asList(...); // 大量用户ID
boolean isSuccess = userService.removeBatchByIds(userIds, 500, true); // 按照批次大小500,启用填充功能进行删除

五、更新

1、接口示例代码

    /**
     * 根据 ID 选择修改
     *
     * @param entity 实体对象
     */
    default boolean updateById(T entity) {
        return SqlHelper.retBool(getBaseMapper().updateById(entity));
    }

    /**
     * 根据 UpdateWrapper 条件,更新记录 需要设置sqlset
     *
     * @param updateWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper}
     */
    default boolean update(Wrapper<T> updateWrapper) {
        return update(null, updateWrapper);
    }

    /**
     * 根据 whereEntity 条件,更新记录
     *
     * @param entity        实体对象
     * @param updateWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper}
     */
    default boolean update(T entity, Wrapper<T> updateWrapper) {
        return SqlHelper.retBool(getBaseMapper().update(entity, updateWrapper));
    }

    /**
     * 根据ID 批量更新
     *
     * @param entityList 实体对象集合
     */
    @Transactional(rollbackFor = Exception.class)
    default boolean updateBatchById(Collection<T> entityList) {
        return updateBatchById(entityList, DEFAULT_BATCH_SIZE);
    }

    /**
     * 根据ID 批量更新
     *
     * @param entityList 实体对象集合
     * @param batchSize  更新批次数量
     */
    boolean updateBatchById(Collection<T> entityList, int batchSize);

    /**
     * TableId 注解存在更新记录,否插入一条记录
     *
     * @param entity 实体对象
     */
    boolean saveOrUpdate(T entity);

2、代码解析

  1. updateById(T entity):根据实体对象的主键ID进行更新操作。当传入一个实体对象时,框架会自动找到与实体对象主键ID相匹配的数据库记录,并将实体对象中非null的属性值更新到数据库中。
  1. update(Wrapper updateWrapper):根据UpdateWrapper封装的条件进行更新操作。UpdateWrapper可以设置复杂的更新条件,如where条件和set更新值,需要调用其相应的方法如eq、ne、set等来构建条件和更新值。
  1. update(T entity, Wrapper updateWrapper):结合实体对象和UpdateWrapper进行更新操作。此时,实体对象除了参与UpdateWrapper中的条件设置外,其非null属性也会参与到更新操作中。
  1. updateBatchById(Collection entityList):根据实体对象集合中每个对象的主键ID进行批量更新操作。默认情况下,会按照框架内部设置的默认批次大小进行分批处理,以减轻数据库压力。
  1. updateBatchById(Collection entityList, int batchSize):类似于前一个方法,但允许自定义批次大小。根据传入的实体对象集合,按照指定的批次大小分批进行更新操作。

6.saveOrUpdate(T entity):根据实体对象中的@TableId注解判断是否存在同主键的记录,如果有则执行更新操作,没有则执行插入操作。此方法简化了在不清楚记录是否存在时的保存逻辑。如果实体对象中的主键已经被赋值,那么就会尝试先查找数据库中是否存在该主键的记录,存在则更新,不存在则插入。

3、应用场景实战

  1. 根据ID选择修改
// 假设我们有一个User实体对象user,想要更新其email属性
User userToUpdate = new User();
userToUpdate.setId(1L);
userToUpdate.setEmail("new@email.com");
boolean isSuccess = userService.updateById(userToUpdate);
  1. 根据UpdateWrapper条件更新记录
// 创建UpdateWrapper实例并设置更新条件和更新内容
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("username", "oldUsername").set("username", "newUsername");
boolean isSuccess = userService.update(updateWrapper);
  1. 根据实体对象及UpdateWrapper条件更新记录
// 假设我们有一个User实体对象user,同时还需要依据某些条件更新
User userToUpdate = new User();
userToUpdate.setId(1L);
userToUpdate.setEmail("new@email.com");

UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("status", "active");

boolean isSuccess = userService.update(userToUpdate, updateWrapper);
  1. 根据ID批量更新
// 假设有一批User对象需要更新
List<User> usersToUpdate = new ArrayList<>();
// ...填充usersToUpdate...

boolean isSuccess = userService.updateBatchById(usersToUpdate);
// 或者自定义批次大小
boolean isSuccessWithCustomBatchSize = userService.updateBatchById(usersToUpdate, 100);
  1. TableId注解存在时更新记录,否则插入一条记录
// 假设我们有一个User实体对象user,如果数据库中存在相同主键的记录,则更新;不存在则插入
User newUser = new User();
newUser.setId(1L); // 设置主键
newUser.setUsername("newUser");
newUser.setEmail("newUser@example.com");
boolean isSuccess = userService.saveOrUpdate(newUser);

以上方法均基于MyBatis-Plus框架,提供了一种简洁的方式来进行数据库记录的更新操作。其中,saveOrUpdate方法特别适用于当不确定记录是否存在时,希望无论记录存在与否都能正确处理的场景。


总结

相关推荐

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-03-26 00:34:03       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-03-26 00:34:03       106 阅读
  3. 在Django里面运行非项目文件

    2024-03-26 00:34:03       87 阅读
  4. Python语言-面向对象

    2024-03-26 00:34:03       96 阅读

热门阅读

  1. C++ day2

    C++ day2

    2024-03-26 00:34:03      44 阅读
  2. 设计模式(1):介绍

    2024-03-26 00:34:03       39 阅读
  3. Solana关闭账户返还租金

    2024-03-26 00:34:03       39 阅读
  4. JVM垃圾回收

    2024-03-26 00:34:03       40 阅读
  5. 洛谷 1443.马的遍历

    2024-03-26 00:34:03       40 阅读
  6. js一些底层

    2024-03-26 00:34:03       44 阅读
  7. 软件设计原则

    2024-03-26 00:34:03       47 阅读
  8. 基于单片机的洗衣机自动化控制电路设计与仿真

    2024-03-26 00:34:03       44 阅读
  9. N诺刷刷题

    2024-03-26 00:34:03       42 阅读
  10. 数据结构之栈

    2024-03-26 00:34:03       49 阅读
  11. ABAP中的内表(看这一篇就够了)

    2024-03-26 00:34:03       39 阅读
  12. HarmonyOS系统开发ArkTS常用组件编程技巧

    2024-03-26 00:34:03       36 阅读