03-MyBatisPlus之DQL编程控制
作者:互联网
三、DQL编程控制
3.1、条件查询方式
- MyBatisPlus将书写复杂的SQL查询条件进行了封装,使用编程的形式完成查询条件的组成
3.1.1、条件查询
-
方式一:按条件查询
-
查询年龄大于18岁的用户
-
@Test // 条件查询----查询年龄大于18的数据 public void selectByCondition() { // 1. 创建一个条件对象 QueryWrapper<User> userQueryWrapper = new QueryWrapper<>(); // 2. 设置条件 userQueryWrapper.gt("age", 18); // 3. 调用mapper对象 List<User> userList = userMapper.selectList(userQueryWrapper); userList.forEach(user -> { log.info("" + user); }); }
-
-
方式二:lamba格式按条件查询(推荐)
-
推荐原因
- 在创建一个普通
QueryWrapper
对象的时候,直接设置条件的时候传递的是("列名", 列值)
,考虑到列名有可能写错或者不存在而在运行时候报错。就可以使用LambdaQueryWarpper
对象来实现
- 在创建一个普通
-
查询年龄大于18的用户
-
@Test // 条件查询---查询年龄大于18的数据(lambda方式) public void selectByConditionWithLambda() { LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>(); userLambdaQueryWrapper.gt(User::getAge, 18); List<User> userList = userMapper.selectList(userLambdaQueryWrapper); userList.forEach(user -> { log.info("" + user); }); }
-
3.1.2、组合条件
-
并且关系(and)
-
查询年龄小于30岁,而且大于10岁的用户
-
@Test // 组合条件查询---并且关系 public void selectByMultiConditionWithLambda() { // 1. 创建条件对象 LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>(); // 2. 设置条件 userLambdaQueryWrapper.lt(User::getAge, 30); userLambdaQueryWrapper.gt(User::getAge, 10); // 调用mapper对象,实现查询 List<User> userList = userMapper.selectList(userLambdaQueryWrapper); userList.forEach(user -> { log.info(user + ""); }); }
-
-
或者关系(or)
-
查询年龄小于10岁或者大于30岁的用户
-
@Test // 组合条件查询---或者关系 public void selectByMultiOrConditionWithLambda() { // 1. 创建条件对象 LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>(); // 2. 设置条件 userLambdaQueryWrapper.gt(User::getAge, 30); userLambdaQueryWrapper.or(); userLambdaQueryWrapper.lt(User::getAge, 10); // 调用mapper对象,实现查询 List<User> userList = userMapper.selectList(userLambdaQueryWrapper); userList.forEach(user -> { log.info(user + ""); }); }
-
3.1.3、NULL值处理
-
问题导入
- 假设现在有一个搜索场景,在多条件查询中,有部分条件的值为空应该要怎么解决?
-
方式一:if语句控制条件追加
-
①、如果最小年龄不为空,则查询大于这个年龄的用户
-
②、如果最大年龄不为空,则查询小于这个年龄的用户
-
@Test // 根据年龄搜索,分别最小年龄,最大年龄,名字, 只要三个变量中任何一个不为空都要作为条件查询 public void selectByMultiNullConditionWithLambda() { // 1. 模拟搜索条件 Integer maxAge = null; Integer minAge = 20; String name = "K"; // 2. 创建条件对象 LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>(); // 3. 设置条件对象的参数 // 如果最大年龄不为空 // ge,le 分别是大于等于,小于等于;gt、lt分别是大于,小于 if (maxAge != null) { userLambdaQueryWrapper.le(User::getAge, maxAge); } // 如果最小年龄不为空 if (minAge != null) { userLambdaQueryWrapper.ge(User::getAge, minAge); } // 如果姓名不为空 if (name != null) { userLambdaQueryWrapper.like(User::getName, name); } // 4. 调用mapper对象实现查询 List<User> userList = userMapper.selectList(userLambdaQueryWrapper); for (User user : userList) { log.info("" + user); } }
-
-
方式二:条件参数控制
-
跟方式一差不多,只不过格式上有点点不一样
-
@Test // 根据年龄搜索,分别最小年龄,最大年龄,名字, 只要三个变量中任何一个不为空都要作为条件查询 public void selectByMultiNullConditionWithLambda2() { // 1. 模拟搜索条件 Integer maxAge = null; Integer minAge = 20; String name = "K"; // 2. 创建条件对象 LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>(); // 3. 设置条件对象的参数 // 如果最大年龄不为空 // ge,le 分别是大于等于,小于等于;gt、lt分别是大于,小于 userLambdaQueryWrapper.le(maxAge != null, User::getAge, maxAge); // 如果最小年龄不为空 userLambdaQueryWrapper.ge(minAge != null, User::getAge, minAge); // 如果姓名不为空 userLambdaQueryWrapper.like(name != null, User::getName, name); // 4. 调用mapper对象实现查询 List<User> userList = userMapper.selectList(userLambdaQueryWrapper); for (User user : userList) { log.info("" + user); } }
-
3.2、查询投影--设置【查询字段、分组、分页】
3.2.1、查询结果包含模型类中部分属性
-
查询所有用户,只显示id,name,age三个属性,不是全部列
-
使用
SELECT 列名1, 列名2...
的方法,查询的结果封装成实体类,其他属性为NULL值 -
@Test // 查询实体类中的部分字段值 (id,name,age) public void selectByPartColumnWithLambda() { // 1. 创建条件对象 LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>(); // 2. 设置条件 userLambdaQueryWrapper.select(User::getId, User::getName, User::getAge); // 3. 调用mapper对象,查询数据 List<User> userList = userMapper.selectList(userLambdaQueryWrapper); for (User user : userList) { log.info("" + user); } }
3.2.2、查询结果包含模型类中未定义的属性
-
如果查询结果包含模型类中未定义的属性,则将每个元素封装成Map对象
-
需求
- 按性别进行分组,统计每组的人数。只显示统计的人数和性别这两个字段
-
使用QueryWrapper包装对象的select方法
-
原因:因为是查询模型类中未定义的属性,使用Lambda表达式的话,就需要实体类有相对应的属性才可以赋值给条件对象,所以这里就不再使用Lambda的方式
-
同时,因为包含实体类中未定义的属性,所以在使用mapper对象的查询方法的时候也不能使用
selectList
而是使用selecMaps
-
@Test // 查询结果中包含实体类中没有定义的属性(统计人数,性别) public void selectByNonPartColumn() { // 1. 创建条件对象 QueryWrapper<User> userQueryWrapper = new QueryWrapper<>(); // 2. 设置查询条件 // select gender count(*) from user group by gender; userQueryWrapper.select("gender", "count(*)"); userQueryWrapper.groupBy("gender"); // 3. 调用mapper对象实现查询 List<Map<String, Object>> mapList = userMapper.selectMaps(userQueryWrapper); for (Map<String, Object> map : mapList) { log.info(map + ""); } }
-
3.3、查询条件
- 我们可以回想一下多条件查询有哪些组合?
- ①、范围匹配(>、=、between)
- ②、模糊匹配(like)
- ③、空判断(null)
- ④、包含性判断(in)
- ⑤、分组(group)
- ⑥、排序(order)
- ...
3.3.1、区间匹配
-
购物设定价格区间、户籍设定年龄区间(le、ge匹配或者between匹配)
-
// 区间匹配(查询年龄10岁到30岁这个范围) @Test public void selectByInterval() { // 1. 创建条件对象 LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>(); // 2. 设置条件 // le、ge匹配 // userLambdaQueryWrapper.ge(User::getAge, 10); // 大于等于10 // userLambdaQueryWrapper.le(User::getAge, 30); // 小于等于30 // betwwen匹配 userLambdaQueryWrapper.between(User::getAge, 10, 30); // 3. 调用mapper对象,实现查询 List<User> userList = userMapper.selectList(userLambdaQueryWrapper); for (User user : userList) { log.info("" + user); } }
3.3.2、模糊匹配
-
查信息,搜索新闻(非全文检索版:like匹配)
-
// 模糊匹配 @Test public void selectByFuzzy() { // 1. 创建条件对象 LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>(); // 2. 设置条件 // like %J% // userLambdaQueryWrapper.like(User::getName, "J"); // like %J // userLambdaQueryWrapper.likeLeft(User::getName, "J"); // like J% userLambdaQueryWrapper.likeRight(User::getName, "J"); // 3. 调用mapper对象 List<User> userList = userMapper.selectList(userLambdaQueryWrapper); for (User user : userList) { log.info("" + user); } }
3.3.3、分组查询聚合函数
-
统计报表(按性别分组,然后计数分组的后的数量)
-
// 分组查询聚合函数 @Test public void selectByGroupAndCount() { // 1. 创建条件对象 QueryWrapper<User> userQueryWrapper = new QueryWrapper<>(); // 这里不用Lambda的原因是查询结果有一个不属于实体类 // 2. 设置条件 userQueryWrapper.select("gender", "count(*) as sum"); userQueryWrapper.groupBy("gender"); // 3. 调用mapper对象,实现查询 List<Map<String, Object>> maps = userMapper.selectMaps(userQueryWrapper); for (Map<String, Object> map : maps) { log.info("" + map); } }
3.3.4、排序和limit
-
需求
- 显示年龄最大的5个用户
-
说明
- ①、对年龄进行降序排序
- ②、仅获取前5条数据
- 也可以考虑2.2节,MyBatis-plus分页操作
-
last()方法说明
- 无视优化规则直接拼接到sql的最后(有sql注入的风险,谨慎使用)
- PS:只能调用一次,多次调用以最后一次为准
-
// order和limit:显示年龄最大的5个用户 @Test public void selectByOrderAndLimit() { // 1. 创建条件对象 LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>(); // 2. 设置条件 userLambdaQueryWrapper.orderByDesc(User::getAge); // desc降序排序 asc升序排序 userLambdaQueryWrapper.last("limit 0, 5"); // 3. 调用mapper对象,实现查询 List<User> users = userMapper.selectList(userLambdaQueryWrapper); for (User user : users) { log.info("" + user); } }
3.4、字段映射与表名映射问题导入
- 如果表的字段和实体类的属性不对应而出现的问题
3.4.1、问题一:表字段和编码属性设计不同步
-
测试步骤
-
1、修改表的列名(后续测试结束再修改回来即可)
-
-- 修改表的列名 ALTER TABLE `user` CHANGE `password` `pwd` VARCHAR(20);
-
-
2、执行查询出现异常,报不知道的列
password
-
3、在模型类属性上方,使用
@TableField
属性注解,通过value
属性,设置当前属性对应的数据库表中的字段值;要不就老老实实更改实体类中的属性- 解决方式1
- 解决方式2
- 解决方式1
-
4、再次执行查询,可以正常运行
-
SQL
语句如下所示 -
SELECT id,name,gender,pwd AS password,age,tel FROM user
-
-
3.4.2、问题二:编码中添加了数据库中未定义的属性
- 测试步骤
- 1、在实体类中添加新的属性
Integer online
- 2、再次执行查询,发现报错
- 1、在实体类中添加新的属性
- 解决办法
- 最简单直接不过就是把这个新增的直接删掉
- 如果在不得不需要该属性的情况下
- 可以在模型类属性上方,使用
@TableField
注解,通过exist
属性,设置属性在数据库表字段中是否存在,默认为true。此属性无法与value同时使用
- 可以在模型类属性上方,使用
- 再次执行查询
- 没有报错,但是
online
的值为空
- 没有报错,但是
3.4.3、问题三:某些字段和属性不参与查询
- 需求
password
这个字段不查询
- 解决办法
- 在模型类属性上方,使用
@TableField
注解,通过select
属性设置该属性是否参与查询,此属性与select()映射配置不冲突 SQL
语句如下所示SELECT id,name,gender,age,tel FROM user
- 因为该字段不参与查询,返回给实体类的时候自然是
null
值
- 在模型类属性上方,使用
3.4.4、问题四:表名和实体类名不同
-
测试步骤
-
1、修改表名,模拟表名和实体类名不同
-
ALTER TABLE user RENAME TO tbl_user
-
-
2、执行查询,运行出现异常
-
-
解决办法
- 在模型类上方,使用
@TableName
注解,通过value
属性,设置当前类对应的数据库表名称;当然直接修改类名也不是不可以,只不过可能会引起连锁反应 - 再次执行查询语句,发现可以成功运行,执行的
SQL
语句如下所示SELECT id,name,gender,password,age,tel FROM tbl_user
- 在模型类上方,使用
标签:03,MyBatisPlus,user,查询,User,条件,DQL,属性,userLambdaQueryWrapper 来源: https://www.cnblogs.com/OnlyOnYourself-lzw/p/16417427.html