展开菜单
首页 精品内容 本月促销 装机必备 Windows PDF教程 macOS软件 IOS软件 Android AI 专题
全部分类

当前位置:

首页 > 编程开发 > Mybatis-Plusselect不去查全部字段和去重问题

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

1、mybatis-plus select查询语句默认是查全部字段 很多刚接触MyBatis-Plus的朋友可能会发现,直接用selectList()方法,生成的SQL会把表里所有字段都查出来。这在大多数场景下没问题,但万一表字段很多,或者你只想取其中几个,查全部字段就显得有点“浪费”了。那么,怎么

本文目录

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

    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();
    

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

    4、mybatis 转义对照表

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

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

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

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