Mybatis-Plus的条件构造器QueryWrapper和UpdateWrapper为开发者提供了强大、灵活的条件构建工具,能够大大简化数据库操作的代码。先介绍一下 QueryWrapper 条件构造器的使用。
首先,我们要打印出 MyBatis-Plus 的SQL日志到控制台,我们需要给“application.properties” 文件增加配置项
mybatis-plus.configuration.log-impl = org.apache.ibatis.logging.stdout.StdOutImpl
这个与 MyBatis 打印SQL日志到控制台是查询不多的。
mybatis.configuration.log-impl = org.apache.ibatis.logging.stdout.StdOutImpl
QueryWrapper 类的主要方法用于SQL语句中where条件的拼接。
第一,方法eq、ne
说明:eq(等于),ne(不等于)
@RequestMapping("/search")
public String search(int cid, Map<String, Object> map){
QueryWrapper<StudentInfo> wrapper = new QueryWrapper();
wrapper.eq("class_id", cid);
List<StudentInfo> list = studentInfoMapper.selectList(wrapper);
map.put("list", list);
return "student";
}
我们使用上一章节的“SpringBootMyBatisPlusDemo”工程来演示。
我们去控制台查看一下SQL日志
上述代码中唯一的缺点就是硬代码写入了表字段名称 “class_id”。
Lambda表达式使用实体类的属性名,可以解决上述问题。
QueryWrapper<StudentInfo> wrapper = new QueryWrapper();
//wrapper.eq("class_id", cid);
wrapper.lambda().eq(StudentInfo::getClassId, cid);
List<StudentInfo> list = studentInfoMapper.selectList(wrapper);
map.put("list", list);
return "student";
他们的执行结果是一样的,生成的SQL语句也是一样的。
我们可以直接使用 QueryWrapper 和 Lambda 的结合体 LambdaQueryWrapper 类。
//QueryWrapper<StudentInfo> wrapper = new QueryWrapper();
//wrapper.eq("class_id", cid);
//wrapper.lambda().eq(StudentInfo::getClassId, cid);
LambdaQueryWrapper<StudentInfo> wrapper = Wrappers.lambdaQuery();
wrapper.eq(StudentInfo::getClassId, cid);
List<StudentInfo> list = studentInfoMapper.selectList(wrapper);
map.put("list", list);
return "student";
他们的执行结果是一样的,生成的SQL语句也是一样的。
如何指定查询字段呢?使用select方法即可。
LambdaQueryWrapper<StudentInfo> wrapper = Wrappers.lambdaQuery();
wrapper.select(StudentInfo::getStuId, StudentInfo::getStuName, StudentInfo::getAddTime);
wrapper.eq(StudentInfo::getClassId, cid);
List<StudentInfo> list = studentInfoMapper.selectList(wrapper);
map.put("list", list);
return "student";
我们只查询id主键,姓名和时间三个表字段,我们直接查看生成的SQL语句吧。
第二,方法gt、ge、lt、le
说明:gt(大于),ge(大于等于),lt(小于),le(小于等于)
wrapper.gt(StudentInfo::getAddTime, "2022-01-01 00:00:00");
我们直接查看生成的SQL语句吧。
第三,方法between、notBetween
说明:between(在值1和值2之间,包括1和2值),notBetween(不在值1和值2之间)
wrapper.between(StudentInfo::getStuAge, 10 ,20);
相当于
wrapper.ge(StudentInfo::getStuAge, 10);
wrapper.le(StudentInfo::getStuAge, 20);
我们直接查看生成的SQL语句吧。
第四,方法 like、notLike、likeLeft、likeRight
说明:like(%值%),notLike(不含%值%),likeLeft(%值),likeRight(值%)
wrapper.like(StudentInfo::getStuName, "小");
我们直接查看生成的SQL语句吧。
第五,方法isNull、isNotNull
说明:isNull(字段 IS NULL),isNotNull(字段 IS NOT NULL)
wrapper.isNotNull(StudentInfo::getAddTime);
我们直接查看生成的SQL语句吧。
第六,方法in、notIn
说明:in(字段 IN 列表),notIn(字段 NOT IN 列表)
List<Integer> inList = Arrays.asList(1,2,3);
wrapper.in(StudentInfo::getStuId, inList);
我们直接查看生成的SQL语句吧。
第七,方法or、and
说明:or(或) ,and(且)
默认情况下,我们上述拼接的Where条件都是 “and” 连接,而 “or” 方法表示紧接着下一个方法使用 “or” 连接。
wrapper.or().eq(StudentInfo::getClassId, 2);
我们直接查看生成的SQL语句吧。
如果我们继续增加条件
wrapper.or().eq(StudentInfo::getClassId, 2);
wrapper.gt(StudentInfo::getAddTime, "2011-01-01 00:00:00");
生成的SQL语句如下
由于 “and” 的优先级大于 “or” ,因此相当于 “or” 把where语句分成了两半去执行。
因此,对于复杂的where条件拼接还是手动比较好,也可以考虑使用“queryWrapper.apply”方法。
第八,方法orderByAsc、orderByDesc
说明:orderByAsc(升序),orderByDesc(降序)
wrapper.orderByAsc(StudentInfo::getStuId);
生成的SQL语句如下
接下来,我们介绍分页查询。
对于MySQL数据库而言,可以使用“limit”命令进行分页,我们只需要根据页码计算数值即可。
例如,每一页显示pageSize=5条记录的话,第一页应该是 limit 0,5;第二页应该是 limit 5,5;第三页应该是:limit 10,5;第四页应该是 limit 15,5;第五页应该是 limit 20,5 ;以此类推。
请注意,分页的前提是要确定排序方式哦,我们使用代码开始演示
@RequestMapping("/student")
public String student(int page, Map<String, Object> map){
page = page == 0 ? 1 : page;
int pageSize = 5;
int from = (page - 1) * pageSize;
QueryWrapper<StudentInfo> wrapper = new QueryWrapper();
wrapper.lambda().orderByAsc(StudentInfo::getStuId);
wrapper.last("limit " + from + "," + pageSize);
List<StudentInfo> list = studentInfoMapper.selectList(wrapper);
map.put("list", list);
return "student";
}
<a href="/student?page=1">student?page=1</a>
我们测试一下,
我们查看第二页
我们之前讲解 “BaseMapper” 的时候,它是支持 “selectPage” 分页查询的。这个方法接受两个参数:一个IPage对象和一个条件构造器QueryWrapper。IPage对象page定义了分页参数(当前页和页大小)。我们还是使用代码来演示一下吧。
int pageSize = 5;
Page<StudentInfo> pageObj = new Page<>(page, pageSize);
QueryWrapper<StudentInfo> wrapper = new QueryWrapper();
wrapper.lambda().orderByAsc(StudentInfo::getStuId);
IPage<StudentInfo> data = studentInfoMapper.selectPage(pageObj, wrapper);
List<StudentInfo> list = data.getRecords();
map.put("list", list);
return "student";
然后还需要添加一个 “分页拦截器”,它是一个配置Bean
package com.demo.config;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
// 添加分页查询拦截器
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return interceptor;
}
}
我们直接查看SQL日志吧
上面是第一页的SQL语句,
上面是第二页的SQL语句,跟我们之前是生成的是一样的。
我们发现,每次分页查询的时候,MyBatisPlus都会查询总的记录数,它主要用来计算总页数的。
注意到 “selectPage” 方法返回的是 IPage<StudentInfo> 对象。
long getTotal(); 代表总页数
long getSize(); 代表每页显示几条记录
long getCurrent(); 代表当前是第几页
java.util.List<T> getRecords(); 代表我们的记录集合
完整 “SpringBootMyBatisPlusDemo” 工程文件下载: https://download.youkuaiyun.com/download/richieandndsc/89888988