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);
}
相关推荐
韦禾水16 小时前
记录一次项目部署到tomcat的异常
java·tomcat
曦月合一16 小时前
树莓派安装jdk、tomcat、vnc、谷歌浏览器开机自启等环境配置
java·tomcat·树莓派
harder32116 小时前
RMP模式的创新突破
开发语言·学习·ios·swift·策略模式
jinanwuhuaguo17 小时前
OpenClaw工程解剖——RAG、向量织构与“记忆宫殿”的索引拓扑学(第十三篇)
android·开发语言·人工智能·kotlin·拓扑学·openclaw
Rust研习社17 小时前
使用 Axum 构建高性能异步 Web 服务
开发语言·前端·网络·后端·http·rust
此剑之势丶愈斩愈烈17 小时前
openssl 自建证书
java
面汤放盐17 小时前
何时使用以及何时不应使用微服务:没有银弹
java·运维·云计算
0xDevNull17 小时前
Spring Boot 自动装配:从原理到实践
java·spring boot·后端
qq_5895681018 小时前
java学习笔记,包括idea快捷键
java·ide·intellij-idea
淘矿人18 小时前
从0到1:用Claude启动你的第一个项目
开发语言·人工智能·git·python·github·php·pygame