第10章 SpringBoot集成MyBatisPlus(6)

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

<think>好的,用户想了解如何在Spring BootMyBatis-Plus中实现分页功能。我需要分步骤解释清楚,确保他们能理解整个过程。首先,我应该确认他们是否已经熟悉基本的Spring BootMyBatis-Plus集成,或者是否需要先进行一些环境配置的说明。不过用户直接问的是分页功能,可能已经有基础了。 接下来,我应该想到MyBatis-Plus内置了分页插件,所以需要先配置这个插件。需要说明在配置类中添加@Bean来注册分页拦截器。这部分很重要,否则分页功能无法生效。 然后是实体类和Mapper接口的创建。需要提醒用户他们的实体类应该对应数据库表,并且Mapper要继承BaseMapper,这样可以直接使用MyBatis-Plus提供的方法。 接下来是Service层的实现,这里可能需要创建Page对象,设置当前页和每页大小,然后调用selectPage方法。这一步需要详细说明Page对象的参数,以及如何从Page对象中获取分页后的数据列表和总记录数。 Controller层需要处理请求参数,比如当前页码和每页数量,通常通过@RequestParam接收,并调用Service的方法返回结果。这里可能需要提到如何将结果封装成统一的响应格式,比如使用Result类。 最后,测试部分要提醒用户通过Postman或者浏览器访问对应的URL,传入正确的参数来验证分页是否生效。可能还需要提到分页查询的条件构造,比如使用QueryWrapper来添加查询条件,这样用户可以实现带条件的分页查询。 需要检查是否有遗漏的步骤,比如依赖的添加,用户是否可能忘记引入MyBatis-Plus的starter。不过可能用户已经知道,但为了保险起见,可以在步骤中提一下需要添加相关依赖,比如mybatis-plus-boot-starter。 另外,分页插件的版本问题是否需要说明?如果用户用的是较旧的版本,配置方式可能不同,但考虑到现在主流的是3.x版本,应该按照最新的方式来写,使用PaginationInnerInterceptor。 可能还需要提醒用户关于分页参数的正确处理,比如防止传入负数或者过大的页码,但也许这属于业务逻辑的增强部分,基础教程中可以先不涉及。 总结下来,回答的结构应该是:配置分页插件 → 创建实体和Mapper → 编写Service → 编写Controller → 测试。每个步骤给出代码示例,并解释关键点,比如Page对象的创建,分页方法的使用,结果的处理等。确保用户按照步骤操作后能成功实现分页功能。</think>以下为使用SpringBoot + MyBatis-Plus实现分页功能的完整步骤: ### 一、添加分页插件配置 在SpringBoot配置类中添加(通常在`MybatisPlusConfig.java`中): ```java @Configuration public class MybatisPlusConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); // 添加分页插件 interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; } } ``` ### 二、创建实体类 ```java @Data @TableName("user") // 对应数据库表名 public class User { @TableId(type = IdType.AUTO) private Long id; private String name; private Integer age; private String email; } ``` ### 三、创建Mapper接口 ```java public interface UserMapper extends BaseMapper<User> { // 继承BaseMapper即拥有基础CRUD方法 } ``` ### 四、Service层实现 ```java @Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService { public Page<User> getPage(Integer current, Integer size) { // 创建分页对象(当前页码,每页数量) Page<User> page = new Page<>(current, size); // 执行分页查询(返回结果会封装到page对象中) return baseMapper.selectPage(page, null); } } ``` ### 五、Controller层 ```java @RestController @RequestMapping("/user") public class UserController { @Autowired private UserService userService; @GetMapping("/page") public Result getByPage( @RequestParam(defaultValue = "1") Integer current, @RequestParam(defaultValue = "10") Integer size) { Page<User> page = userService.getPage(current, size); return Result.success() .data("list", page.getRecords()) // 当前页数据列表 .data("total", page.getTotal()); // 总记录数 } } ``` ### 六、测试验证 访问接口(示例): ``` GET http://localhost:8080/user/page?current=2&size=5 ``` 响应结果示例: ```json { "code": 200, "msg": "success", "data": { "list": [ // 第2页的5条数据... ], "total": 35 } } ``` ### 补充说明: 1. **条件分页查询**:可以使用`QueryWrapper`添加查询条件 ```java QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.like("name", "张"); baseMapper.selectPage(page, wrapper); ``` 2. **自定义分页SQL**:对于复杂查询,可在Mapper.xml中自定义SQL: ```xml <select id="selectUserPage" resultType="User"> SELECT * FROM user WHERE age > #{age} </select> ``` 接口方法: ```java IPage<User> selectUserPage(Page<User> page, @Param("age") Integer age); ``` 3. **前端分页参数**:建议对`current`和`size`进行校验(最小值限制)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值