MybatisPlus
提供了很多的插件功能,进一步拓展其功能。目前已有的插件有:
PaginationInnerInterceptor
:自动分页TenantLineInnerInterceptor
:多租户DynamicTableNameInnerInterceptor
:动态表名OptimisticLockerInnerInterceptor
:乐观锁IllegalSQLInnerInterceptor
:sql
性能规范BlockAttackInnerInterceptor
:防止全表更新与删除注意:
使用多个分页插件的时候需要注意插件定义顺序,建议使用顺序如下:
- 多租户,动态表名
- 分页,乐观锁
- sql 性能规范,防止全表更新与删除
这里我们以分页插件为里来学习插件的用法。
在未引入分页插件的情况下,MybatisPlus
是不支持分页功能的,IService
和BaseMapper
中的分页方法都无法正常起效。
所以,我们必须配置分页插件。
在项目中新建一个配置类:
其代码如下:
package com.itheima.mp.config;
import com.baomidou.mybatisplus.annotation.DbType;
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 MybatisConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
// 初始化核心插件
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 添加分页插件
PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
paginationInnerInterceptor.setMaxLimit(1000L);
interceptor.addInnerInterceptor(paginationInnerInterceptor);
return interceptor;
}
}
编写一个分页查询的测试:
@Test
void testPageQuery(){
int pageNo = 1, pageSize = 2;
// 1.准备分页条件
// 1.1.分页条件
Page<User> page = Page.of(pageNo, pageSize);
// 1.2.排序条件 (先按照balance 升序,如果存在一致的balance 再按照 id 进行升序排序)
page.addOrder(new OrderItem("balance",true));
page.addOrder(new OrderItem("id",true));
// 2.分页查询
Page<User> p = userService.page(page);
// 3.解析
long total = p.getTotal(); // 总记录数
System.out.println("total = "+total);
long pages = p.getPages(); // 总页数
System.out.println("pages = "+pages);
List<User> users = p.getRecords(); // 分页结果
users.forEach(System.out::println);
}
运行的SQL
如下:
现在要实现一个用户分页查询的接口,接口规范如下:
返回值如下:
这里需要定义3个实体:
UserQuery
:分页查询条件的实体,包含分页
、排序参数
、过滤条件
PageDTO
:分页结果实体,包含总条数
、总页数
、当前页数据
UserVO
:用户页面视图实体由于UserQuery
之前已经定义过了,并且其中已经包含了过滤条件,具体代码如下:
package com.itheima.mp.domain.query;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(description = "用户查询条件实体")
public class UserQuery {
@ApiModelProperty("用户名关键字")
private String name;
@ApiModelProperty("用户状态:1-正常,2-冻结")
private Integer status;
@ApiModelProperty("余额最小值")
private Integer minBalance;
@ApiModelProperty("余额最大值")
private Integer maxBalance;
}
其中缺少的仅仅是分页条件,而分页条件不仅仅用户分页查询需要,以后其它业务也都有分页查询的需求。因此建议将分页查询条件单独定义为一个PageQuery
实体:
PageQuery
是前端提交的查询参数,一般包含四个属性:
pageNo
:页码pageSize
:每页数据条数sortBy
:排序字段isAsc
:是否升序package com.itheima.mp.domain.query;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(description = "分页查询实体")
public class PageQuery {
@ApiModelProperty("页码")
private Long pageNo;
@ApiModelProperty("页码")
private Long pageSize;
@ApiModelProperty("排序字段")
private String sortBy;
@ApiModelProperty("是否升序")
private Boolean isAsc;
}
然后,让我们的UserQuery
继承这个实体:
分页实体PageDTO
:
代码如下:
package com.itheima.mp.domain.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
@Data
@ApiModel(description = "分页结果")
public class PageDTO<T> {
@ApiModelProperty("总条数")
private Long total;
@ApiModelProperty("总页数")
private Long pages;
@ApiModelProperty("集合")
private List<T> list;
}
最后是UserVO
,在之前有写过:
在UserController
中定义分页查询用户的接口:
代码如下:
@ApiOperation("根据分页条件查询用户的接口")
@GetMapping("/page")
public PageDTO<UserVO> queryUsersPage(UserQuery query){
return userService.queryUsersPage(query);
}
然后在IUserService
中创建queryUsersPage
方法:
PageDTO<UserVO> queryUsersPage(PageQuery query);
接下来,在UserServiceImpl
中实现该方法:
@Override
public PageDTO<UserVO> queryUsersPage(UserQuery query) {
String name = query.getName();
Integer status = query.getStatus();
Integer maxBalance = query.getMaxBalance();
Integer minBalance = query.getMinBalance();
// 1.1.分页条件
Page<User> page = Page.of(query.getPageNo(), query.getPageSize());
// 1.2.排序条件
if (StrUtil.isNotBlank(query.getSortBy())) { // 排序条件不为空
page.addOrder(new OrderItem(query.getSortBy(), query.getIsAsc()));
} else { // 排序条件为空,默认按照更新时间进行降序排序
page.addOrder(new OrderItem("update_time", false));
}
// 2.分页查询
Page<User> p = lambdaQuery()
.like(name != null, User::getUsername, name)
.eq(status != null, User::getStatus, status)
.ge(minBalance != null, User::getBalance, minBalance)
.le(maxBalance != null, User::getBalance, maxBalance)
.page(page);
// 3.封装VO结果
PageDTO<UserVO> dto = new PageDTO<>();
// 3.1.总条数
dto.setTotal(p.getTotal());
// 3.2.总页数
dto.setPages(p.getPages());
// 3.3.当前页数据
List<User> records = p.getRecords();
if (CollUtil.isEmpty(records)) {
dto.setList(Collections.emptyList());
return dto;
}
// 3.4.拷贝user的vo
dto.setList(BeanUtil.copyToList(records, UserVO.class));
// 4.返回
return dto;
}
启动项目,在测试效果: