商城首页欢迎来到中国正版软件门户

您的位置:首页 >Mybatis-Plusselect不去查全部字段和去重问题

Mybatis-Plusselect不去查全部字段和去重问题

  发布于2026-04-24 阅读(0)

扫一扫,手机访问

1、mybatis-plus select查询语句默认是查全部字段

很多刚接触MyBatis-Plus的朋友可能会发现,直接用selectList()方法,生成的SQL会把表里所有字段都查出来。这在大多数场景下没问题,但万一表字段很多,或者你只想取其中几个,查全部字段就显得有点“浪费”了。那么,怎么精准地指定查询字段呢?主要有两种方法。

Mybatis-Plusselect不去查全部字段和去重问题

为了更直观地说明,我们先来看下示例表结构:

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表的nameage字段,可以利用QueryWrapperselect(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_idcreate_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_idcreate_time字段已经被成功排除在外了。这种方法在实体类字段较多时尤其好用。

2、Mybatis plus实现Distinct去重功能

说到去重,方法其实不少。你可以用分组查询,也可以在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,那么写法应该是:

	QueryWrapper queryWrapper = new QueryWrapper<>();
	queryWrapper.select("DISTINCT no,type").orderByAsc("oldlu");
	return mapper.selectList(queryWrapper);

这样一来,生成的SQL就会包含DISTINCT关键字,实现对指定字段组合的去重查询。

3、Mybatis plus实现in操作

IN查询在业务中太常见了。如果参数本身就是一个List这样的集合,那直接传给in方法就行。但有时候,我们的参数是另一个查询的结果集,需要先取出来再塞进IN条件里。如果手动拼SQL或者写复杂接口,就显得有点麻烦。其实,用MyBatis-Plus可以很优雅地搞定。

我们来看一个典型的场景和步骤:

// 1. 先查询到一个实体对象列表
List userList = 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();

这套组合拳打下来,逻辑清晰,代码也简洁。本质上就是先把数据捞出来处理成集合,再交给QueryWrapperin方法去构建SQL条件。

4、mybatis 转义对照表

在XML中写动态SQL时,经常会遇到小于号(<)、大于号(>)这些特殊字符。直接写的话,XML解析器会误认为它们是标签的一部分,从而导致解析错误。这个问题困扰过不少开发者。

解决办法其实不复杂,就是做一下转义替换。下面这个对照表,建议收藏备用:

<<=>>=&"
<<=>>=&'"

光说不练假把式,看个代码例子就明白了。比如下面这个分页查询的XML片段,在比较日期时就用到了转义符: