当前位置: 首页 > news >正文

详细梳理 MyBatis-Plus 的 QueryWrapper 和 LambdaQueryWrapper的入门到精通

文章目录

    • 一、QueryWrapper?
    • 二、LambdaQueryWrapper
    • 三、常用条件方法总结
    • 四、动态条件(推荐写法)
    • 五、分页查询
    • 六、复杂查询案例
      • 6.1. 多条件 OR
      • 6.2. GROUP BY + HAVING
    • 七、最佳实践
    • 八、完整示例
      • 8.1. pom.xml 依赖
      • 8.2. 实体类 User.java
      • 8.3. Mapper 接口 UserMapper.java
      • 8.4. Service 层 UserService.java
      • 8.5. Controller 层 UserController.java
      • 8.6. CSV 工具类 CsvUtil.java

什么是 QueryWrapper 和 LambdaQueryWrapper?

  • QueryWrapper:基于字符串的字段名构造查询条件,简单直观,适合快速开发,但需要手动输入字段名,容易因拼写错误导致问题。
  • LambdaQueryWrapper:基于 Lambda 表达式,通过实体类的 getter 方法引用字段,类型安全,避免硬编码,提高代码可读性和维护性。

两者功能类似,但 LambdaQueryWrapper 更适合现代化 Java 开发(Java 8+)。

一、QueryWrapper?

QueryWrapper 是 MyBatis-Plus 提供的 条件构造器,用于拼接 SQL 的 WHERE、ORDER BY、GROUP BY 等语句,不需要自己写 SQL。

基本用法:

QueryWrapper<User> query = new QueryWrapper<>();
query.eq("name", "张三")  // WHERE name = '张三'.ge("age", 18)       // AND age >= 18.like("email", "qq"); // AND email LIKE '%qq%'// 查询
List<User> users = userMapper.selectList(query);

生成 SQL:

SELECT * FROM user WHERE name = '张三' AND age >= 18 AND email LIKE '%qq%';

二、LambdaQueryWrapper

推荐使用 LambdaQueryWrapper —— 避免硬编码字段名,用 Lambda 表达式 替代,保证字段变更时编译报错,避免运行时出错。

基本用法:

LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(User::getName, "张三").ge(User::getAge, 18).like(User::getEmail, "qq");// 查询
List<User> users = userMapper.selectList(wrapper);

生成 SQL(同上):

SELECT * FROM user WHERE name = '张三' AND age >= 18 AND email LIKE '%qq%';

User::getName 自动对应实体类字段 name,不怕写错。

三、常用条件方法总结

方法说明示例
eq等于eq(“name”, “张三”) → name = ‘张三’
ne不等于ne(“status”, 1)
gt大于gt(“age”, 20)
ge大于等于ge(“age”, 18)
lt小于lt(“age”, 60)
le小于等于le(“age”, 60)
between区间between(“age”, 18, 30)
like模糊匹配like(“name”, “三”)
likeLeft左模糊likeLeft(“name”, “三”) → name LIKE ‘%三’
likeRight右模糊likeRight(“name”, “三”) → name LIKE ‘三%’
in IN查询in(“id”, Arrays.asList(1,2,3))
notInNOT INnotIn(“id”, list)
orderByAsc升序orderByAsc(“age”)
orderByDesc降序orderByDesc(“create_time”)
isNull为空isNull(“email”)
isNotNull不为空isNotNull(“email”)
orOR 条件eq(“status”, 1).or().eq(“status”, 2)
nested嵌套nested(w -> w.eq(“status”, 1).or().eq(“status”, 2))

四、动态条件(推荐写法)

实际开发中,经常需要 参数为空时不加条件:

String name = "张三";
Integer age = null;LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(name != null, User::getName, name).ge(age != null, User::getAge, age);

只会拼接 name = ‘张三’,不会拼接 age >= ?。

五、分页查询

Page<User> page = new Page<>(1, 10); // 第1页, 每页10条
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.ge(User::getAge, 18);IPage<User> result = userMapper.selectPage(page, wrapper);System.out.println("总数: " + result.getTotal());
System.out.println("数据: " + result.getRecords());

六、复杂查询案例

6.1. 多条件 OR

wrapper.eq(User::getStatus, 1).or(w -> w.eq(User::getAge, 20).like(User::getName, "李"));

SQL:

WHERE status = 1 OR (age = 20 AND name LIKE '%李%')

6.2. GROUP BY + HAVING

QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.select("dept_id, COUNT(*) as cnt").groupBy("dept_id").having("cnt > {0}", 10);

七、最佳实践

  • 能用 LambdaQueryWrapper 就不用 QueryWrapper,避免硬编码。

  • 条件要动态拼接,利用 (condition, column, value) 三元参数。

  • 分页时用 selectPage,大数据量避免 selectList。

  • 多表场景:推荐用 MyBatis-Plus 配合 自定义 SQL + Wrapper,或用 联表插件。

八、完整示例

以下是完整的 Spring Boot + MyBatis-Plus + LambdaQueryWrapper + CSV 导出示例,包含以下内容:

  • 依赖配置(Maven)

  • 实体类(User)

  • Mapper 接口

  • Service 层(使用 LambdaQueryWrapper 查询)

  • Controller 层(导出为 CSV)

  • CSV 工具类

8.1. pom.xml 依赖

<dependencies><!-- Spring Boot Web --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- MyBatis-Plus --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.5</version></dependency><!-- MySQL 驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-j</artifactId><scope>runtime</scope></dependency><!-- CSV 工具:OpenCSV --><dependency><groupId>com.opencsv</groupId><artifactId>opencsv</artifactId><version>5.9</version></dependency>
</dependencies>

8.2. 实体类 User.java

package com.example.demo.entity;import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;@Data
@TableName("user")
public class User {@TableIdprivate Long id;private String name;private Integer age;private String email;
}

8.3. Mapper 接口 UserMapper.java

package com.example.demo.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.demo.entity.User;
import org.apache.ibatis.annotations.Mapper;@Mapper
public interface UserMapper extends BaseMapper<User> {
}

8.4. Service 层 UserService.java

package com.example.demo.service;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.demo.entity.User;
import com.example.demo.mapper.UserMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;import java.util.List;@Service
@RequiredArgsConstructor
public class UserService {private final UserMapper userMapper;public List<User> findUsers(Integer minAge) {return userMapper.selectList(new LambdaQueryWrapper<User>().ge(User::getAge, minAge)  // 年龄大于等于.orderByAsc(User::getAge) // 按年龄排序);}
}

8.5. Controller 层 UserController.java

package com.example.demo.controller;import com.example.demo.entity.User;
import com.example.demo.service.UserService;
import com.example.demo.util.CsvUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;@RestController
@RequiredArgsConstructor
public class UserController {private final UserService userService;@GetMapping("/export/users")public void exportUsers(HttpServletResponse response) throws IOException {List<User> users = userService.findUsers(18); // 查询年龄 >= 18// 设置响应头response.setContentType("text/csv");response.setCharacterEncoding("UTF-8");response.setHeader("Content-Disposition", "attachment; filename=users.csv");// 写入 CSVCsvUtil.writeUsersToCsv(users, response.getWriter());}
}

8.6. CSV 工具类 CsvUtil.java

package com.example.demo.util;import com.example.demo.entity.User;
import com.opencsv.CSVWriter;import java.io.Writer;
import java.util.List;public class CsvUtil {public static void writeUsersToCsv(List<User> users, Writer writer) {try (CSVWriter csvWriter = new CSVWriter(writer)) {// 写表头String[] header = {"ID", "姓名", "年龄", "邮箱"};csvWriter.writeNext(header);// 写数据for (User user : users) {String[] data = {String.valueOf(user.getId()),user.getName(),String.valueOf(user.getAge()),user.getEmail()};csvWriter.writeNext(data);}} catch (Exception e) {throw new RuntimeException("写 CSV 文件失败", e);}}
}

启动项目后,访问:

http://localhost:8080/export/users

会自动下载 users.csv,里面是查询出的用户数据。

在这里插入图片描述


“人的一生会经历很多痛苦,但回头想想,都是传奇”。


http://www.dtcms.com/a/354326.html

相关文章:

  • App中分发中的防盗链开发是做什么的?防盗链有什么作用?什么是防盗链?
  • vscode 如何调试 python 2.7
  • 【PyTorch】基于YOLO的多目标检测项目(一)
  • 免费开源图片压缩工具|绿色版本地运行,支持批量压缩+格式转换,不上传数据,隐私安全有保障!
  • 解决delphi label 在timer下闪烁的问题
  • 字节面试手撕题:神经网络模型损失函数与梯度推导
  • CSS(面试)
  • Mojomox-在线 AI logo 设计工具
  • 从“流量焦虑”到“稳定增长”:用内容平衡术解锁Adsense变现新密码
  • 电子器械如何统一管理系统权限?一场IT治理的“攻坚战”
  • 第二十九天:重载、重写和覆盖
  • 【网络】iptables MASQUERADE作用
  • 机器学习与Backtrader结合量化交易
  • 无人机抗干扰技术要点解析
  • O2OA移动办公 × Flutter:一次开发,跨平台交付
  • 【C++】深入解析构造函数初始化
  • Docker 镜像重命名【打上新的标签】
  • AI应用图文解说--百度智能云实现语音聊天
  • Python爬虫获取1688商品列表与图片信息
  • 【免驱】一款基于AI8H2K08U芯片的USB转RS485模块,嵌入式工程师调试好帮手!
  • Web 自动化测试常用函数实战(一)
  • 如何防御安全标识符 (SID) 历史记录注入
  • 嵌入式学习day38
  • 怎样选择合适的报表系统?报表系统的主要功能有什么
  • PLC_博图系列☞基本指令”S_PULSE:分配脉冲定时器参数并启动“
  • PyTorch闪电入门:张量操作与自动微分实战
  • Wxml2Canvas在组件中的渲染获取不到元素问题
  • vue 海康视频插件
  • Java Spring Boot 集成淘宝 SDK:实现稳定可靠的商品信息查询服务
  • AI鱼塘,有你画的鱼吗?