[Mybatis-Plus笔记] MybatisPlus-03-QueryWrapper条件构造器入门
一、准备工作
为了更好的理解条件构造器,建议配置 Mybatis-Plus 的日志输出到控制台
在 yaml 配置文件中加入下面内容:
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
如此配置后,我们可以在控制台看到 Mybatis-Plus 生成的 SQL 语句
二、条件构造器入门
1. 使用方式
(1)普通 QueryWrapper
下面的测试类中,实现了从表中查询 age 字段小于 20 的用户
然后利用 selectList 方法,将条件构造器作为参数传入,即可得到符合条件的数据
@SpringBootTest
public class MybatisPlusTest {
@Autowired
UserMapper userMapper;
@Test
void testQueryWrapper() {
QueryWrapper condition = new QueryWrapper();
// 方法名 lt 表示小于,参数是字段名与值
condition.lt("age", 20);
List<User> users = userMapper.selectList(condition);
System.out.println(users);
}
}
[注意]
- 不指定 QueryWrapper 的泛型无法进行链式编程
SQL 语句为:
SELECT id,name,age,email FROM user WHERE (age < ?)
(2)lambda 方式 QueryWrapper
通过指定实体类的 get 方法来确定列,避免了写错类名带来的麻烦
需要指定泛型为实体类,并以 lambda() 方法开头
可以链式编程
@SpringBootTest
public class MybatisPlusTest {
@Autowired
UserMapper userMapper;
@Test
void testQueryWrapper() {
QueryWrapper<User> condition = new QueryWrapper<User>();
// condition.lt("age", 20);
condition.lambda().lt(User::getAge, 20);
List<User> users = userMapper.selectList(condition);
System.out.println(users);
}
}
SQL 语句也是:
SELECT id,name,age,email FROM user WHERE (age < ?)
(3)LambdaQueryWrapper
使用 LambdaQueryWrapper 就不用指定再写 lambda() 方法开头了
但不可再通过列名来指定字段
@SpringBootTest
public class MybatisPlusTest {
@Autowired
UserMapper userMapper;
@Test
void testQueryWrapper() {
LambdaQueryWrapper<User> condition = new LambdaQueryWrapper<User>();
// condition.lt("age", 20); // 不可用
condition.lt(User::getAge, 20);
List<User> users = userMapper.selectList(condition);
System.out.println(users);
}
}
SQL 语句依然是:
SELECT id,name,age,email FROM user WHERE (age < ?)
2. 条件的逻辑连接
(1)与运算
对同一个条件构造器添加多个条件,默认用与运算(或者说且运算)连接
如下例完成 20 <= age <= 30 的条件构造(ge 和 le 分别表示 >= 和 <=)
@SpringBootTest
public class MybatisPlusTest {
@Autowired
UserMapper userMapper;
@Test
void testQueryWrapper() {
QueryWrapper<User> condition = new QueryWrapper<User>();
condition.lambda()
.ge(User::getAge, 20).le(User::getAge, 30);
List<User> users = userMapper.selectList(condition);
System.out.println(users);
}
}
SQL 语句为:
SELECT id,name,age,email FROM user WHERE (age >= ? AND age <= ?)
(2)或运算
多个条件间用 or() 方法分隔,条件就会用或运算连接
如下例完成 age < 20 || age > 30 的条件构造(lt 和 gt 分别表示 < 和 >)
@SpringBootTest
public class MybatisPlusTest {
@Autowired
UserMapper userMapper;
@Test
void testQueryWrapper() {
QueryWrapper<User> condition = new QueryWrapper<User>();
condition.lambda().
lt(User::getAge, 20).or().gt(User::getAge, 30);
List<User> users = userMapper.selectList(condition);
System.out.println(users);
}
}
SQL 语句为:
SELECT id,name,age,email FROM user WHERE (age < ? OR age > ?)
(3)括号
条件构造器中,and() 方法表示括号(或者说嵌套),而不是且运算
我们需要将括号中的内容作为参数传入 and() 方法
例如,我们需要在年龄低于 20 或者高于 35 的用户中,找出使用 @gmail 邮箱的用户
可以像下面这样:
@SpringBootTest
public class MybatisPlusTest {
@Autowired
UserMapper userMapper;
@Test
void testQueryWrapper() {
QueryWrapper<User> condition = new QueryWrapper<User>();
condition.lambda()
.and(
i -> i.lt(User::getAge, 20).or().gt(User::getAge, 35)
).likeLeft(User::getEmail, "@gmail.com");
List<User> users = userMapper.selectList(condition);
System.out.println(users);
}
}
关于 and() 方法中的 lambda 表达式,在 idea 中 按住 ctrl 将鼠标放在 i 上,可以看到,i 指代的是一个 LambdaQueryWrapper<User>
SQL 语句为:
SELECT id,name,age,email FROM user WHERE ((age < ? OR age > ?) AND email LIKE ?)
参数为 :
Parameters: 20(Integer), 35(Integer), %@gmail.com(String)
可见 likeLeft() 方法自动给参数左侧加上了 % 通配符
类似的还有 likeRight() 在右侧加 %
like() 在左右侧都加 %
3. 更多条件判断方法
lt, le, gt, ge 这些代表条件判断的代码,最早还是在 Shell 脚本中见到的
想要了解更多的话推荐这一篇文章:Mybatis Plus详解(三)——条件构造器详解
三、补充
1. 增加布尔值参数
在条件构造器添加条件是,可以再加入一个 boolean 值表示是否要将此条件加入。
看下例中,服务层实现了根据年龄区间查询用户的功能:
@Service
public class UserServiceImpl implements UserService {
@Autowired
UserMapper userMapper;
@Override
public List<User> selectByAgeRange(Integer low, Integer high) {
QueryWrapper<User> condition = new QueryWrapper<>();
condition.lambda()
.ge(User::getAge, low)
.lt(User::getAge, high);
return userMapper.selectList(condition);
}
}
但是参数为 null 时会怎样呢?测试一下看看:
@SpringBootTest
public class UserServiceTest {
@Autowired
UserService userService;
@Test
void testSelectByAgeRange() {
List<User> users = userService.selectByAgeRange(null, 20);
System.out.println(users);
}
}
用 null 和 20 做参数,一般希望能忽略下限,查询小于 20 岁的用户,但实际上没有查到任何结果
Mybatis-Plus 日志如下:
==> Preparing: SELECT id,name,age,email FROM user WHERE (age >= ? AND age < ?)
==> Parameters: null, 20(Integer)
<== Total: 0
如果某个参数为空,则不将此条件加入构造,可以这样写:
@Service
public class UserServiceImpl implements UserService {
@Autowired
UserMapper userMapper;
@Override
public List<User> selectByAgeRange(Integer low, Integer high) {
QueryWrapper<User> condition = new QueryWrapper<>();
condition.lambda()
.ge(low != null, User::getAge, low)
.lt(high != null, User::getAge, high);
return userMapper.selectList(condition);
}
}
ge 和 lt 方法中多了一个布尔值参数,当这个参数为真时才会加入此条件
再次执行测试,日志如下:
==> Preparing: SELECT id,name,age,email FROM user WHERE (age < ?)
==> Parameters: 20(Integer)
<== Columns: id, name, age, email
<== Row: 2, Tao Chi Yuen, 17, chiyuentao@icloud.com
<== Row: 4, Ueno Hikari, 18, hikari9@hotmail.com
<== Row: 12, Mildred Ramirez, 19, ramirez2@icloud.com
<== Total: 3
2. 查询映射
select() 方法可以指定查询的内容,参数为字符串可变参数,将表的字段名做为参数传入
默认查询所有字段,如果没有参数传入则无效
Mybatis-Plus 会在多个参数间添加逗号,然后放在 SQL 语句的 SELECT 之后
我们直接用 SQL 语句作为参数传入也可以
select() 方法的效果不会叠加,多次调用 select() 方法时以最后一次为准,最后一次无参数不会覆盖之前的
示例:
@SpringBootTest
public class MybatisPlusTest {
@Autowired
UserMapper userMapper;
@Test
void testSelect() {
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.select("age");
wrapper.select("name, email");
wrapper.select("name AS userName, email AS userEmail");
wrapper.select();
userMapper.selectList(wrapper);
}
}
Mybatis-Plus 日志如下:
==> Preparing: SELECT name AS userName, email AS userEmail FROM user
==> Parameters:
<== Columns: userName, userEmail
<== Row: Pauline Cole, paulic59@icloud.com
<== Row: Tao Chi Yuen, chiyuentao@icloud.com
<== Total: 2
3. selectMaps() 方法
如果查询到的数据是不能装进实体类中的,就要调用 selectMaps() 方法了,用 List<Map<String, Object>> 接收结果
比如聚合函数查询平均年龄,如下:
@SpringBootTest
public class MybatisPlusTest {
@Autowired
UserMapper userMapper;
@Test
void testSelectMaps() {
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.select("AVG(age) AS averageAge");
List<Map<String, Object>> maps = userMapper.selectMaps(wrapper);
System.out.println(maps);
BigDecimal averageAge = (BigDecimal) maps.get(0).get("averageAge");
System.out.println("averageAge = " + averageAge);
}
}
另外,AVG() 聚合函数得到的结果是 BigDecimal 类型,而不是 double
Mybatis-Plus 日志如下:
==> Preparing: SELECT AVG(age) AS averageAge FROM user
==> Parameters:
<== Columns: averageAge
<== Row: 21.8438
<== Total: 1