MyBatis-Plus 通用 Service(IService)详解与实战
MyBatis-Plus 的通用 Service 层(IService)封装了大量 CRUD 操作,极大简化了开发流程。本文将基于User实体类,全面实现 IService 接口的核心方法,并提供完整测试案例。
一、核心组件介绍
1. IService 接口
MyBatis-Plus 提供的IService接口是 Service 层的核心,定义了 40 + 常用方法,涵盖:
- 基础 CRUD(新增、删除、修改、查询)
- 批量操作
- 条件查询
- 分页查询
- 逻辑删除等
2. ServiceImpl 实现类
ServiceImpl<M extends BaseMapper<T>, T>是 IService 的默认实现,需要指定:
- 泛型 M:对应的 Mapper 接口
- 泛型 T:实体类
二、环境准备
1. 依赖引入(pom.xml)
<dependencies>
<!-- Spring Boot Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- MyBatis-Plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
<!-- 数据库驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- 测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
2. 核心接口与类定义
(1)UserMapper 接口
package com.qcby.mybatisplus1.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.qcby.mybatisplus1.domain.User;
public interface UserMapper extends BaseMapper<User> {
}
(2)UserService 接口
package com.qcby.mybatisplus1.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.qcby.mybatisplus1.domain.User;
public interface UserService extends IService<User> {
}
(3)UserServiceImpl 实现类
package com.qcby.mybatisplus1.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qcby.mybatisplus1.domain.User;
import com.qcby.mybatisplus1.mapper.UserMapper;
import com.qcby.mybatisplus1.service.UserService;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}
三、IService 核心方法实现与测试
1. 测试类基础配置
package com.qcby.mybatisplus1.service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qcby.mybatisplus1.domain.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.*;
import static org.junit.jupiter.api.Assertions.*;
@SpringBootTest
public class UserServiceTest {
@Autowired
private UserService userService;
}
2. 新增操作
(1)单个新增
@Test
public void testSave() {
User user = new User(null, "张三", 20, "zhangsan@qq.com");
boolean result = userService.save(user);
assertTrue(result);
System.out.println("新增后的ID:" + user.getId()); // 自动生成的ID
}
(2)批量新增
@Test
public void testSaveBatch() {
List<User> userList = new ArrayList<>();
userList.add(new User(null, "李四", 22, "lisi@qq.com"));
userList.add(new User(null, "王五", 25, "wangwu@qq.com"));
boolean result = userService.saveBatch(userList);
assertTrue(result);
userList.forEach(user -> System.out.println("批量新增ID:" + user.getId()));
}
3. 修改操作
(1)根据 ID 修改
@Test
public void testUpdateById() {
User user = new User(1L, "张三更新", 21, "zhangsan_update@qq.com");
boolean result = userService.updateById(user);
assertTrue(result);
}
(2)条件修改
@Test
public void testUpdate() {
// 将名字为"李四"的年龄改为23
User updateUser = new User();
updateUser.setAge(23);
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name", "李四");
boolean result = userService.update(updateUser, queryWrapper);
assertTrue(result);
}
4. 删除操作
(1)根据 ID 删除
@Test
public void testRemoveById() {
boolean result = userService.removeById(1L);
assertTrue(result);
}
(2)批量删除
@Test
public void testRemoveByIds() {
List<Long> ids = Arrays.asList(2L, 3L);
boolean result = userService.removeByIds(ids);
assertTrue(result);
}
(3)条件删除
@Test
public void testRemove() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("age", 25); // 删除年龄为25的用户
boolean result = userService.remove(queryWrapper);
assertTrue(result);
}
5. 查询操作
(1)根据 ID 查询
@Test
public void testGetById() {
User user = userService.getById(1L);
assertNotNull(user);
System.out.println("查询结果:" + user);
}
(2)批量查询
@Test
public void testListByIds() {
List<Long> ids = Arrays.asList(1L, 2L);
List<User> userList = userService.listByIds(ids);
assertFalse(userList.isEmpty());
userList.forEach(System.out::println);
}
(3)条件查询
@Test
public void testList() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.ge("age", 22) // 年龄>=22
.like("email", "qq.com"); // 邮箱包含qq.com
List<User> userList = userService.list(queryWrapper);
userList.forEach(System.out::println);
}
(4)分页查询
@Test
public void testPage() {
Page<User> page = new Page<>(1, 2); // 第1页,每页2条
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.orderByDesc("age"); // 按年龄倒序
IPage<User> userIPage = userService.page(page, queryWrapper);
System.out.println("总页数:" + userIPage.getPages());
System.out.println("总记录数:" + userIPage.getTotal());
userIPage.getRecords().forEach(System.out::println);
}
6. 其他常用方法
(1)查询记录总数
@Test
public void testCount() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.gt("age", 20); // 统计年龄>20的用户数
long count = userService.count(queryWrapper);
System.out.println("符合条件的记录数:" + count);
}
(2)判断记录是否存在
@Test
public void testExists() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name", "张三");
boolean exists = userService.exists(queryWrapper);
System.out.println("是否存在:" + exists);
}
四、分页插件配置(必需)
使用分页功能需要配置分页插件,否则分页不生效:
package com.qcby.mybatisplus1.config;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyBatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 添加分页插件
interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return interceptor;
}
}
五、总结
MyBatis-Plus 的 IService 接口为我们提供了丰富的 CRUD 操作方法,主要分为以下几类:
操作类型 | 核心方法 |
新增 | save()、saveBatch() |
修改 | updateById()、update() |
删除 | removeById()、removeByIds()、remove() |
查询 | getById()、listByIds()、list()、page() |
统计 | count()、exists() |
通过继承 ServiceImpl 实现类,我们无需编写具体实现代码,直接调用这些方法即可完成数据库操作,极大提高了开发效率。
实际开发中,可根据业务需求灵活组合这些方法,复杂查询可通过 QueryWrapper 构建条件。
后续可以结合具体业务场景,进一步扩展 Service 层的功能,比如添加自定义查询方法等。