IService——使用和新增

目录

[4 IService](#4 IService)

[4.1 概述](#4.1 概述)

[4.2 创建接口和实现类](#4.2 创建接口和实现类)

[4.3 IService接口里的方法](#4.3 IService接口里的方法)

[4.3.1 新增](#4.3.1 新增)

普通批量插入

按指定批次批量插入

普通批量修改插入

按指定批次批量修改插入


4 IService

4.1 概述

  1. MyBatisPlus 对 Service 层 CRUD 操作进行通用封装,提供 IService 接口和其实现类 ServiceImpl作为核心封装载体,里面的 CRUD 方法命名使用同一的规范。
  2. IService方法命名规则:CRUD 方法采用特定前缀区分,避免与 Mapper 层混淆 ------get 对应单行查询、remove 对应删除操作、list 对应集合查询、page 对应分页查询。
  3. 泛型设计:IService 接口支持泛型 ,T 可指代任意实体对象,适配不同数据表的 CRUD 需求。
  4. 进阶建议:若项目存在自定义通用 Service 方法的需求(非 MP 自带 CRUD),可以自己创建一个 IBaseService 接口(叫什么随意),且该接口需继承 MyBatis-Plus 提供的 IService 基类,实现通用方法的统一管理与复用。
  5. 底层原理:IService 利用 Java 8 默认方法特性(具体见++10 jdk1.8新功能++),为多数 CRUD 方法提供预先实现;MyBatisPlus 同时提供 ServiceImpl 实现类,其核心职责是持有并注入 Mapper 实例、提供 getBaseMapper() 方法(供 IService 默认方法调用 Mapper 层操作),还会显式实现部分复杂方法(如 saveOrUpdate)。
  6. 使用方式:自定义 Service 接口(如 UserService)需继承 IService,自定义 Service 实现类(如 UserServiceImpl)需继承 ServiceImpl<具体Mapper, T> 并实现自定义 Service 接口,即可直接复用 IService 中的所有通用 CRUD 方法,无需手动编写重复逻辑。
  7. 参考资料:官方文档地址为 https://baomidou.com/pages/49cc81/#service-crud-%E6%8E%A5%E5%8F%A3

4.2 创建接口和实现类

复制代码
package com.qcby.mybatisplus1122.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.qcby.mybatisplus1122.entity.User;

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

注:IService 的 T 必须和对应的 BaseMapper 的 T 一致。这是因为 IService 的通用方法最终会调用 BaseMapper 的方法,若类型不匹配,Mapper 层无法识别 Service 层传递的类型,导致数据库操作的表与实体不对应。

复制代码
package com.qcby.mybatisplus1122.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qcby.mybatisplus1122.entity.User;
import com.qcby.mybatisplus1122.mapper.UserMapper;
import com.qcby.mybatisplus1122.service.UserService;
import org.springframework.stereotype.Service;

/**
* ServiceImpl实现了IService,提供了IService中基础功能的实现
* 若ServiceImpl无法满足业务需求,则可以使用自定的UserService定义方法,并在实现类中实现 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper,User> implements UserService {

}

注:

ServiceImpl中:

复制代码
public class ServiceImpl<M extends BaseMapper<T>, T> implements IService<T>
  • 第一个参数M 必须是BaseMapper的子类(即UserMapper必须继承BaseMapper)。
  • 第二个参数T 必须要和BaseMapper的T一致。并且要和上面代码中的IService 的 T 完全相同。因为 ServiceImpl 实现了 IService。

4.3 IService接口里的方法

新建测试类

复制代码
@SpringBootTest
public class ServiceTest {

    @Autowired
    private UserService userService;
}

4.3.1 新增

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

    /**

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

    @Test
    public void Save(){
    User user = new User(null, "张三", 23, "zhangsan@qcby.com");
    //INSERT INTO user ( id, name, age, email ) VALUES ( ?, ?, ?, ? )
    //1992568912290516994
    Boolean result = userService.save(user);
    System.out.println(result);
    }

  2. 批量插入
    SQL长度有限制,海量数据插入单条SQL无法实行,因此MP将批量插入放在了通用Service中实现,而不是通用Mapper。

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

注:@Transactional(rollbackFor = Exception.class)的解释见4 Spring配置事务。

DEFAULT_BATCH_SIZE表示按默认批次插入。默认是1000.

复制代码
@Test
public void SaveBatch(){
    User user1 = new User(null, "张三", 23, "zhangsan@qcby.com");
    User user2 = new User(null, "张三", 23, "zhangsan@qcby.com");
    List<User> list = new ArrayList<>();
    list.add(user1);
    list.add(user2);
    //INSERT INTO user ( id, name, age, email ) VALUES ( ?, ?, ?, ? )
    Boolean result = userService.saveBatch(list);
    System.out.println(result);
}
按指定批次批量插入
复制代码
/**
 * 插入(批量)
 *
 * @param entityList 实体对象集合
 * @param batchSize  插入批次数量
 */
boolean saveBatch(Collection<T> entityList, int batchSize);
  • Collection entityList:

    • Collection: 这是 Java 中的一个集合接口,List、Set 等都实现了这个接口。所以你可以传入一个 List、Set 等。
    • T: 这是一个泛型参数,代表你要操作的实体类类型,比如 User、Product 等。
  • int batchSize:

  • int: 整数类型。

  • 作用: 这个参数指定了每一批次插入的数据量。

  • boolean: 返回一个布尔值。

    • true: 表示所有批次的插入操作都成功了。
  • false: 表示至少有一个批次的插入操作失败了。
    注:

  • 需要batchSize的原因是因为,如果你的 entityList 里有 1000 个对象,并且你把 batchSize 设置为 1000,那么 MyBatis-Plus 会尝试构造一个非常长的 SQL 语句。如果太长会超过数据库接收的最大数据包大小,导致操作失败。此外数据库解析和执行如此长的一条 SQL 语句本身就是一个性能负担。

  • 如果我分批插入如果同样是 1000 个对象,但你把 batchSize 设置为 100,那么 MyBatis-Plus 会自动将这 1000 个对象分成 10 个批次,循环执行 10 次插入操作,每次只插入 100 条数据(写在同一个insert语句里)。这样可以避免SQL语句过长,并且性能更好。

    @Test
    public void SaveBatch1(){
    User user1 = new User(null, "张三", 23, "zhangsan@qcby.com");
    User user2 = new User(null, "张三", 23, "zhangsan@qcby.com");
    List<User> list = new ArrayList<>();
    list.add(user1);
    list.add(user2);
    //INSERT INTO user ( id, name, age, email ) VALUES ( ?, ?, ?, ? ) 执行两次
    Boolean result = userService.saveBatch(list,1);
    System.out.println(result);
    }

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

这个方法是 MyBatis-Plus 提供的批量 "保存或更新"工具,核心逻辑是:

  • 遍历传入的 entityList 集合,对每个实体:

    • 若实体的主键已存在(数据库中能查到对应主键的记录),则执行更新操作(UPDATE);
  • 若实体的主键不存在(数据库中无对应主键的记录),则执行插入操作(INSERT);
    简单说:能更则更,不能更则插,无需你手动判断是新增还是修改。

    @Test
    public void saveOrUpdateBatch(){
    User user1 = new User(1992568912290516994l, "王五", 23, "zhangsan@qcby.com");
    User user2 = new User(5l, "张三", 23, "zhangsan@qcby.com");
    List<User> list = new ArrayList<>();
    list.add(user1);
    list.add(user2);
    //先select在决定要干什么
    Boolean res = userService.saveOrUpdateBatch(list);
    System.out.println(res);
    }

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

@Test
public void saveOrUpdateBatch1(){
    User user1 = new User(1992568912290516994l, "王五1", 56, "zhangsan@qcby.com");
    User user2 = new User(9l, "张三", 23, "zhangsan@qcby.com");
    User user3 = new User(7l, "张三", 23, "zhangsan@qcby.com");
    User user4 = new User(8l, "张三", 23, "zhangsan@qcby.com");
    List<User> list = new ArrayList<>();
    list.add(user1);
    list.add(user2);
    list.add(user3);
    list.add(user4);
    //先select在决定要干什么
    Boolean res = userService.saveOrUpdateBatch(list,2);
    System.out.println(res);
}
相关推荐
计算机安禾1 小时前
【C语言程序设计】第33篇:二级指针与指针数组
c语言·开发语言·数据结构·c++·算法·visual studio code·visual studio
falldeep1 小时前
LLM中的强化学习方法分类
开发语言·人工智能·机器学习
sjmaysee2 小时前
@RestController注解
java
魑魅魍魉都是鬼2 小时前
Android:java kotlin 单例模式
android·java·单例模式
LSL666_2 小时前
5 MySQL驱动类选择与数据库连接 URL 时区配置
数据库·mysql·mybatis·mybatisplus
WG_172 小时前
Linux44:POSIX信号量:
java·开发语言
WZTTMoon2 小时前
Spring Boot 启动报错:OpenFeign 隐性循环依赖,排查了整整一下午
java·spring boot·后端·spring cloud·feign
俩个逗号。。2 小时前
Kotlin 扩展函数详解
开发语言·kotlin