MyBatis-Plus IService 接口全量方法实现与测试(续)
上一篇我们实现了 IService 的核心方法,本文将补充剩余方法的实现与测试,涵盖批量操作、链式查询、复杂查询等场景,基于User实体类完成全部 40 + 方法的实战案例。
六、批量操作扩展方法
1. 带批次大小的批量新增
@Test
public void testSaveBatchWithSize() {
List<User> userList = new ArrayList<>();
for (int i = 0; i < 1500; i++) { // 超过默认1000条
userList.add(new User(null, "批量用户" + i, 20 + i % 10, "batch" + i + "@qq.com"));
}
// 指定批次大小为500
boolean result = userService.saveBatch(userList, 500);
assertTrue(result);
}
2. 批量新增或修改(saveOrUpdateBatch)
@Test
public void testSaveOrUpdateBatch() {
List<User> userList = new ArrayList<>();
// 已存在的用户(ID存在则更新)
userList.add(new User(1L, "张三更新", 22, "zhangsan_new@qq.com"));
// 新用户(ID不存在则新增)
userList.add(new User(null, "赵六", 28, "zhaoliu@qq.com"));
boolean result = userService.saveOrUpdateBatch(userList);
assertTrue(result);
}
@Test
public void testSaveOrUpdateBatchWithSize() {
List<User> userList = new ArrayList<>();
for (int i = 0; i < 1200; i++) {
// 模拟部分已有ID的用户
User user = new User(i < 500 ? (long)i : null, "用户" + i, 20 + i % 10, "user" + i + "@qq.com");
userList.add(user);
}
// 指定批次大小为300
boolean result = userService.saveOrUpdateBatch(userList, 300);
assertTrue(result);
}
3. 带填充的删除操作
@Test
public void testRemoveByIdWithFill() {
// 注意:需要实体类配置逻辑删除字段并开启自动填充
boolean result = userService.removeById(1L, true);
System.out.println("带填充删除结果:" + result);
}
@Test
public void testRemoveBatchByIdsWithFill() {
List<Long> ids = Arrays.asList(2L, 3L);
boolean result = userService.removeBatchByIds(ids, true);
System.out.println("带填充批量删除结果:" + result);
}
@Test
public void testRemoveBatchByIdsWithSize() {
List<Long> ids = new ArrayList<>();
for (long i = 4; i < 1004; i++) {
ids.add(i);
}
// 指定批次大小为200
boolean result = userService.removeBatchByIds(ids, 200);
assertTrue(result);
}
@Test
public void testRemoveBatchByIdsWithSizeAndFill() {
List<Long> ids = new ArrayList<>();
for (long i = 1004; i < 2004; i++) {
ids.add(i);
}
boolean result = userService.removeBatchByIds(ids, 200, true);
assertTrue(result);
}
七、修改操作扩展
1. 条件修改(无实体参数)
@Test
public void testUpdateWithoutEntity() {
// 将所有年龄>30的用户邮箱后缀改为@163.com
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.gt("age", 30);
queryWrapper.set("email", "update@163.com"); // 直接在条件中设置修改内容
boolean result = userService.update(queryWrapper);
assertTrue(result);
}
2. 批量修改
@Test
public void testUpdateBatchById() {
List<User> userList = new ArrayList<>();
userList.add(new User(1L, "张三批量更新", 23, "zhangsan_batch@qq.com"));
userList.add(new User(2L, "李四批量更新", 24, "lisi_batch@qq.com"));
boolean result = userService.updateBatchById(userList);
assertTrue(result);
}
@Test
public void testUpdateBatchByIdWithSize() {
List<User> userList = new ArrayList<>();
for (long i = 1; i < 1001; i++) {
userList.add(new User(i, "批量更新用户" + i, 25, "batch_update" + i + "@qq.com"));
}
// 指定批次大小为300
boolean result = userService.updateBatchById(userList, 300);
assertTrue(result);
}
3. 新增或修改(带条件)
@Test
public void testSaveOrUpdateWithWrapper() {
User user = new User();
user.setName("条件新增或修改");
user.setAge(30);
user.setEmail("condition@qq.com");
// 按name作为查询条件
QueryWrapper<User> updateWrapper = new QueryWrapper<>();
updateWrapper.eq("name", "条件新增或修改");
boolean result = userService.saveOrUpdate(user, updateWrapper);
assertTrue(result);
}
八、查询操作扩展
1. 复杂查询(getOne 带异常控制)
@Test
public void testGetOneWithException() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.gt("age", 20);
// 当查询结果超过1条时,是否抛出异常
try {
User user = userService.getOne(queryWrapper, false); // 不抛出异常,返回第一条
System.out.println("查询结果:" + user);
} catch (Exception e) {
e.printStackTrace();
}
}
2. 地图查询与对象转换
@Test
public void testGetMap() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("id", 1L);
Map<String, Object> userMap = userService.getMap(queryWrapper);
System.out.println("Map查询结果:" + userMap);
assertNotNull(userMap);
}
@Test
public void testGetObj() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("id", 1L);
// 将查询结果转换为String类型(获取name字段)
String userName = userService.getObj(queryWrapper, obj -> {
if (obj instanceof User) {
return ((User) obj).getName();
}
return null;
});
System.out.println("转换结果:" + userName);
}
3. 批量查询扩展
@Test
public void testListMaps() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.lt("age", 25);
List<Map<String, Object>> mapList = userService.listMaps(queryWrapper);
System.out.println("Map列表大小:" + mapList.size());
assertFalse(mapList.isEmpty());
}
@Test
public void testListObjs() {
// 查询所有用户的ID并转换为Long类型
List<Long> idList = userService.listObjs((obj) -> {
if (obj instanceof User) {
return ((User) obj).getId();
}
return null;
});
idList.forEach(id -> System.out.println("用户ID:" + id));
}
@Test
public void testListObjsWithWrapper() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.gt("age", 22);
// 获取符合条件的用户邮箱
List<String> emailList = userService.listObjs(queryWrapper, obj -> {
if (obj instanceof User) {
return ((User) obj).getEmail();
}
return null;
});
emailList.forEach(email -> System.out.println("用户邮箱:" + email));
}
4. 分页查询扩展
@Test
public void testPageMaps() {
Page<Map<String, Object>> page = new Page<>(1, 5);
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.orderByAsc("age");
IPage<Map<String, Object>> mapIPage = userService.pageMaps(page, queryWrapper);
System.out.println("总页数:" + mapIPage.getPages());
System.out.println("当前页数据:" + mapIPage.getRecords());
}
九、链式查询与更新
1. 普通链式查询
@Test
public void testQueryChain() {
// 链式查询:年龄>20且邮箱包含qq.com的用户
List<User> userList = userService.query()
.gt("age", 20)
.like("email", "qq.com")
.list();
userList.forEach(System.out::println);
}
@Test
public void testLambdaQueryChain() {
// Lambda链式查询(类型安全)
List<User> userList = userService.lambdaQuery()
.gt(User::getAge, 20)
.like(User::getEmail, "qq.com")
.list();
userList.forEach(System.out::println);
}
2. 链式更新
@Test
public void testUpdateChain() {
// 链式更新:将name为"张三"的用户年龄改为25
boolean result = userService.update()
.eq("name", "张三")
.set("age", 25)
.update();
assertTrue(result);
}
@Test
public void testLambdaUpdateChain() {
// Lambda链式更新(类型安全)
boolean result = userService.lambdaUpdate()
.eq(User::getName, "李四")
.set(User::getAge, 26)
.update();
assertTrue(result);
}
3. Kotlin 链式操作(Java 中使用示例)
@Test
public void testKtQuery() {
// Kotlin风格链式查询(需引入Kotlin依赖)
List<User> userList = userService.ktQuery()
.gt(User::getAge, 20)
.list();
userList.forEach(System.out::println);
}
@Test
public void testKtUpdate() {
boolean result = userService.ktUpdate()
.eq(User::getName, "王五")
.set(User::getAge, 27)
.update();
assertTrue(result);
}
十、方法分类与使用场景总结
方法类型 | 核心方法 | 适用场景 |
基础 CRUD | save()、updateById()、removeById()、getById() | 单条数据的增删改查 |
批量操作 | saveBatch()、updateBatchById()、removeBatchByIds() | 大量数据的批量处理 |
条件操作 | update()、remove()、list() | 带查询条件的操作 |
分页查询 | page()、pageMaps() | 大数据量分页展示 |
链式操作 | lambdaQuery()、lambdaUpdate() | 复杂条件的类型安全查询 |
转换操作 | getMap()、getObj()、listObjs() | 结果集的格式转换 |
十一、注意事项
- 事务控制:批量操作方法默认添加@Transactional注解,支持事务回滚
- 批次大小:默认批次大小为 1000,可根据数据库性能调整
- 逻辑删除:带useFill参数的方法用于逻辑删除,需配合实体类注解@TableLogic使用
- 类型安全:Lambda 表达式的链式操作可避免字符串硬编码,推荐使用
- 异常处理:getOne方法当结果集大于 1 时,需指定是否抛出异常