您的位置:首页 >Mybatis-Plusselect不去查全部字段和去重问题
发布于2026-04-24 阅读(0)
扫一扫,手机访问
很多刚接触MyBatis-Plus的朋友可能会发现,直接用selectList()方法,生成的SQL会把表里所有字段都查出来。这在大多数场景下没问题,但万一表字段很多,或者你只想取其中几个,查全部字段就显得有点“浪费”了。那么,怎么精准地指定查询字段呢?主要有两种方法。

为了更直观地说明,我们先来看下示例表结构:
CREATE TABLE `user` ( `id` bigint(20) NOT NULL COMMENT '主键', `name` varchar(30) DEFAULT NULL COMMENT '姓名', `age` int(11) DEFAULT NULL COMMENT '年龄', `email` varchar(50) DEFAULT NULL COMMENT '邮箱', `manager_id` bigint(20) DEFAULT NULL COMMENT '直属上级id', `create_time` datetime DEFAULT NULL COMMENT '创建时间', PRIMARY KEY (`id`), KEY `manager_fk` (`manager_id`), CONSTRAINT `manager_fk` FOREIGN KEY (`manager_id`) REFERENCES `user` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
第一种方法:明确指定字段名
假设我们只需要查询user表的name和age字段,可以利用QueryWrapper的select(String... columns)方法,直接把字段名传进去就行。
@Test
public void selectByWrapper10() {
QueryWrapper queryWrapper = new QueryWrapper<>();
queryWrapper.select("name", "age").like("name", "雨");
List users = userMapper.selectList(queryWrapper);
users.forEach(System.out::println);
}
执行后,看看控制台输出的SQL日志,效果立竿见影:
DEBUG==> Preparing: SELECT name,age FROM user WHERE name LIKE ?
DEBUG==> Parameters: %雨%(String)
TRACE<== Columns: name, age
TRACE<== Row: 张雨琪, 31
TRACE<== Row: 刘红雨, 31
DEBUG<== Total: 2
看,SQL语句确实只查询了我们指定的两个字段。
第二种方法:动态排除特定字段
有时候情况反过来,我们想查询除了某几个字段外的所有字段。比如,不想查manager_id和create_time。这时候,select方法另一个重载形式就派上用场了,它允许我们通过Lambda表达式动态判断。
@Test
public void selectByWrapper11() {
QueryWrapper queryWrapper = new QueryWrapper<>();
queryWrapper.select(User.class, info -> !info.getColumn().equals("manager_id")
&& !info.getColumn().equals("create_time"));
List users = userMapper.selectList(queryWrapper);
users.forEach(System.out::println);
}
再来看看生成的SQL:
DEBUG==> Preparing: SELECT id,name,age,email FROM user
DEBUG==> Parameters:
TRACE<== Columns: id, name, age, email
TRACE<== Row: 1087982257332887553, 大boss, 40, boss@baomidou.com
TRACE<== Row: 1088248166370832385, 王天风, 25, wtf@baomidou.com
TRACE<== Row: 1088250446457389058, 李艺伟, 28, lyw@baomidou.com
TRACE<== Row: 1094590409767661570, 张雨琪, 31, zjq@baomidou.com
TRACE<== Row: 1094592041087729666, 刘红雨, 31, lhm@baomidou.com
DEBUG<== Total: 5
可以看到,manager_id和create_time字段已经被成功排除在外了。这种方法在实体类字段较多时尤其好用。
说到去重,方法其实不少。你可以用分组查询,也可以在Ja va层用Set处理。但如果就想在SQL层面用DISTINCT关键字,MyBatis-Plus也完全支持,而且用法相当直接。
关键就在select方法里,把DISTINCT关键字和字段名一起作为字符串传进去即可:
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.select("DISTINCT no,type").orderByAsc("oldlu");
return mapper.selectList(queryWrapper);
注意,这里查询出的结果类型,需要根据你的实体类来定。比如,如果你的实体类是User,那么写法应该是:
QueryWrapperqueryWrapper = new QueryWrapper<>(); queryWrapper.select("DISTINCT no,type").orderByAsc("oldlu"); return mapper.selectList(queryWrapper);
这样一来,生成的SQL就会包含DISTINCT关键字,实现对指定字段组合的去重查询。
IN查询在业务中太常见了。如果参数本身就是一个List这样的集合,那直接传给in方法就行。但有时候,我们的参数是另一个查询的结果集,需要先取出来再塞进IN条件里。如果手动拼SQL或者写复杂接口,就显得有点麻烦。其实,用MyBatis-Plus可以很优雅地搞定。
我们来看一个典型的场景和步骤:
// 1. 先查询到一个实体对象列表 ListuserList = userService.selectById(id); // 2. 准备一个结果集,用来存放需要用于IN查询的字段值 List resultList = new ArrayList<>(); // 3. 遍历集合,提取出我们需要的ID值 userList .forEach(item->{ resultList.add(item.getYouNeedId()); }); // 4. 构造查询条件,使用in方法 QueryWrapper qw = new QueryWrapper<>(); qw.in("you_need_id", resultList); // 5. 执行查询(这里以分页查询为例,其他方法同理) IPage userIPage = userMapper.selectPage(page, qw); // 6. 返回结果 return contractRecordIPage.getRecords();
这套组合拳打下来,逻辑清晰,代码也简洁。本质上就是先把数据捞出来处理成集合,再交给QueryWrapper的in方法去构建SQL条件。
在XML中写动态SQL时,经常会遇到小于号(<)、大于号(>)这些特殊字符。直接写的话,XML解析器会误认为它们是标签的一部分,从而导致解析错误。这个问题困扰过不少开发者。
解决办法其实不复杂,就是做一下转义替换。下面这个对照表,建议收藏备用:
| < | <= | > | >= | & | ’ | " |
|---|---|---|---|---|---|---|
| < | <= | > | >= | & | ' | " |
光说不练假把式,看个代码例子就明白了。比如下面这个分页查询的XML片段,在比较日期时就用到了转义符:
以上就是关于MyBatis-Plus在日常开发中几个实用技巧的分享,涵盖了字段选择、去重查询、IN条件构建以及XML转义这些常见痛点。掌握这些,能让你的代码更高效、更清晰。希望这些经验能为大家提供一些参考和帮助。
您可能感兴趣的文章:
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
9