目录
- 前言
- 1. QueryWrapper
- 2. 函数
- 3. Demo
前言
原本都是在Mapper文件中修改,直到看到项目中使用了QueryWrapper这个函数,大致了解了用法以及功能,发现还可以!
对此此贴为科普帖以及笔记帖
1. QueryWrapper
MyBatis-Plus 是 MyBatis 的增强工具包,它简化了 MyBatis 的开发流程,提供了一些常用功能的增强和简化方法。其中,QueryWrapper 是 MyBatis-Plus 中用于构建动态条件查询的一个重要类。QueryWrapper 可以用于构建 SQL 的 WHERE 子句,动态地拼接条件,以实现灵活的查询。
查看其层级结构:
对于Wrapper主体父类其下有关系的类,主要作用如下:
Wrapper:
Wrapper 接口是用于构建查询条件的基础接口。
它声明了一些常用的设置条件的方法,比如 eq、ne、like 等。
QueryWrapper 和 UpdateWrapper 都实现了这个接口。AbstractWrapper:
AbstractWrapper 是一个抽象类,实现了 Wrapper 接口。
为常用的条件设置方法提供了默认实现。AbstractLambdaWrapper:
AbstractLambdaWrapper 继承自 AbstractWrapper,引入了用于类型安全查询的 lambda 表达式。
它专为使用 Java lambda 表达式指定查询条件的实体设计。LambdaQueryWrapper:
LambdaQueryWrapper 是 AbstractLambdaWrapper 的具体实现,用于查询操作。
支持使用 lambda 表达式以类型安全的方式指定查询条件。
对于实体属性名称的编译时检查,避免运行时错误。LambdaUpdateWrapper:
LambdaUpdateWrapper 是 AbstractLambdaWrapper 的具体实现,用于更新操作。
允许使用 lambda 表达式以类型安全的方式更新实体字段。
类似于 LambdaQueryWrapper,它通过编译时检查帮助避免运行时错误。QueryWrapper:
QueryWrapper 是 AbstractWrapper 的具体实现,用于查询操作。
提供了各种方法用于设置不同的查询条件,如 eq、ne、like 等
2. 函数
以下是 QueryWrapper 常用的一些函数和用法:
- eq、ne、gt、ge、lt、le:
这些方法分别表示等于、不等于、大于、大于等于、小于、小于等于的条件。
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("name", "John")
.ne("age", 25)
.gt("salary", 50000)
.ge("create_time", "2022-01-01")
.lt("update_time", "2023-01-01")
.le("status", 1);
- like、notLike、likeLeft、likeRight:用于构建模糊查询条件。
wrapper.like("name", "John")
.notLike("description", "test")
.likeLeft("code", "abc")
.likeRight("email", "@domain.com");
- isNull、isNotNull:用于构建判空条件。
wrapper.isNull("email")
.isNotNull("phone");
- in、notIn:用于构建 IN 和 NOT IN 条件。
wrapper.in("role", "admin", "user", "guest")
.notIn("status", 0, 2, 3);
- between、notBetween:用于构建 BETWEEN 和 NOT BETWEEN 条件。
wrapper.between("age", 20, 30)
.notBetween("salary", 50000, 80000);
- or、and:用于构建 OR 和 AND 条件,可以嵌套使用。
wrapper.and(i -> i.eq("name", "John").ne("age", 25))
.or(i -> i.like("name", "Tom").ge("age", 30));
- orderBy、orderByAsc、orderByDesc:用于指定排序方式。
wrapper.orderBy(true, true, "age")
.orderByAsc("create_time")
.orderByDesc("update_time");
- groupBy、having:用于指定分组和分组后的条件。
wrapper.groupBy("department")
.having("SUM(salary) > 50000");
- apply:用于直接拼接 SQL 片段。
wrapper.apply("DATE_FORMAT(create_time, '%Y-%m-%d') = '2022-01-01'");
这些方法可以根据实际需要组合使用,动态地构建查询条件。
在 MyBatis-Plus 中,QueryWrapper 的使用使得动态条件查询变得更加方便和灵活。
关于该类的具体源码,由于比较多,我分析一个给大家看看,感兴趣的可以自已去看源码:
eq判断相等的函数:
- 该类继承了AbstractWrapper类:
- 找到AbstractWarpper类中重写的eq方法,对应其参数以及其怎么实现:(具体参数讲解可继续点击其addCondition)
- 查看其具体函数执行
columnToString函数是将属性转换为string属性
formatSql函数将val进行格式化
doIt函数判断condition条件为true,则执行sql片段的组装
3. Demo
大致相关的User类别以及Mapper需要进行创建
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
// Assuming you have a User entity with fields like id, name, age, email, etc.
public class UserQueryExample {
public static void main(String[] args) {
// Example: Constructing a dynamic query
// Create a QueryWrapper instance
QueryWrapper<User> wrapper = new QueryWrapper<>();
// Basic conditions
wrapper.eq("name", "John")
.between("age", 25, 35)
.like("email", "@domain.com");
// Nested conditions using lambda
wrapper.and(qw -> qw.gt("salary", 50000).or().lt("salary", 80000));
// Order by
wrapper.orderByAsc("age");
// Applying additional conditions using apply
wrapper.apply("DATE_FORMAT(create_time, '%Y-%m-%d') = '2022-01-01'");
// Print the generated SQL
System.out.println("Generated SQL: " + wrapper.getSqlSegment());
// If you are using MyBatis-Plus mapper, you can directly use the wrapper in your query
// For example, if you have a UserMapper, you can do something like:
// List<User> userList = userMapper.selectList(wrapper);
}
}
以往我们都是使用Mapper文件中的sql进行编写,对于以往的sql语句:
存在一些问题:
-
SQL 注入风险: 直接拼接字符串可能导致 SQL 注入的风险,因为用户输入的数据没有经过严格的检查和处理。
-
可读性差: 通过字符串拼接构建 SQL,代码的可读性较差,难以维护和理解。
-
不够灵活: 需要手动处理各种情况,代码容易变得冗长。
相比之下,使用 MyBatis-Plus 的 QueryWrapper,可以更清晰、安全、易维护地构建动态查询条件,避免了手动拼接 SQL 字符串的繁琐和潜在的安全问题。
对于该类的更多例子可以看这篇文章的比较:Mybatis-plus 动态条件查询QueryWrapper的使用