1、问题描述
MyBatis-Plus使用Ipage分页查询数据时,删除最后一页全部数据后,再次调用查询接口,显示当前页无数据。
例如:共有21条数据,每页显示10条数据,删除最后一条数据(第3页的唯一一条数据)后,页面跳转至第二页,但是显示无数据。
分页查询代码如下(Repository层):
//分页查询列表
@Override
public IPage<SiteType> getAllByOrgIdAndPagination(String orgId, Pagination pagination) {
//Page从第1页开始,Pagination从第0页开始
IPage<SiteType> page = new Page<>(pagination.getCurrent() + 1, pagination.getPageSize());
Wrapper<SiteType> queryWrapper = Wrappers.lambdaQuery(SiteType.class)
.eq(SiteType::getOrgId, orgId)
.orderByDesc(SiteType::getCreateTime);
return siteTypeMapper.selectPage(page,queryWrapper);
}
2、问题原因
查询接口只查询当前页的数据,在最后一页(第3页)删除最后一条数据后,前端仍查询当前页(第3页)的数据,结果为空。
因此需要判断当前页是否有数据,若无数据,需要进行处理,如跳转至前一页或首页。本文介绍后端处理方法。
3、解决方法
方法一:手动判断当前页是否有数据(不推荐)
在Service层判断当前页是否有数据,若无数据,查询前一页:
@Override
public SiteTypeListDTO getSiteTypeList(SiteTypeListRequest request) {
User user = ContextUserHolder.get();
IPage<SiteType> siteTypeIPage = siteTypeRepository.getAllByOrgIdAndPagination(user.getOrgId(), request.getPagination());
Pagination pagination = new Pagination(siteTypeIPage.getCurrent() - 1, siteTypeIPage.getSize(), siteTypeIPage.getTotal(), null);
//如果当前页没有数据(如删除某页的唯一一条数据),重新获取前一页的记录
//例如查询第3页时,current:2,pageSize:10,如果total<=20,则current-=1
if (pagination.getCurrent() * pagination.getPageSize() >= pagination.getTotal() && pagination.getCurrent() != 0) {
//request中的current减1
request.getPagination().setCurrent(request.getPagination().getCurrent() - 1);
siteTypeIPage = siteTypeRepository.getAllByOrgIdAndPagination(user.getOrgId(), request.getPagination());
pagination.setCurrent(pagination.getCurrent() - 1);
}
List<SiteTypeDTO> siteTypeList = siteTypeIPage.getRecords().stream()
.map(siteType -> convert2SiteTypeDTO(siteType, user.getLocale())).collect(Collectors.toList());
return new SiteTypeListDTO(siteTypeList, pagination);
}
方法二:设置分页插件属性(推荐)
参考mybatis plus分页插件设置,配置mybatis plus分页器,设置overflow属性为true(查询页面超出范围时,跳转至首页):
@Configuration
public class MybatisConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
//设置分页插件属性:请求页超出范围时,返回首页
PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
paginationInnerInterceptor.setOverflow(true);
interceptor.addInnerInterceptor(paginationInnerInterceptor);
return interceptor;
}
}
设置Overflow属性为true后,删除最后一页最后一条数据后页面空白的问题就解决了。
修改Overflow处理逻辑:无数据时查询前一页数据
查看PaginationInnerInterceptor.class源码发现,页面超出范围后的处理是查询第1页数据:
protected boolean continuePage(IPage<?> page) {
if (page.getTotal() <= 0L) {
return false;
} else {
if (page.getCurrent() > page.getPages()) {
if (!this.overflow) {
return false;
}
this.handlerOverflow(page);
}
return true;
}
}
//页面超出范围时,返回第1页
protected void handlerOverflow(IPage<?> page) {
page.setCurrent(1L);
}
为了保持删除后的查询逻辑一致(删除后返回当页,当页无数据返回前一页,而不是首页),可以重写handlerOverflow方法如下:
①新建NewPaginationInnerInterceptor 类,重写handlerOverflow方法:
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author Tony brings water
* @date 2021/8/18 14:10
* 分页删除某页唯一记录后,自动跳转至前一页(默认实现是跳转至首页)
*/
@Data
@NoArgsConstructor
public class NewPaginationInnerInterceptor extends PaginationInnerInterceptor {
private DbType dbType;
public NewPaginationInnerInterceptor(DbType dbType) {
this.dbType = dbType;
}
@Override
protected void handlerOverflow(IPage<?> page) {
//查询前一页
page.setCurrent(page.getCurrent() - 1);
}
}
具体跳转逻辑可根据业务自定义。
②修改MyBatis Plus配置,使用NewPaginationInnerInterceptor:
@Configuration
public class MybatisConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
//设置分页插件属性:请求页超出范围时,返回前一页
NewPaginationInnerInterceptor paginationInnerInterceptor = new NewPaginationInnerInterceptor(DbType.MYSQL);
paginationInnerInterceptor.setOverflow(true);
interceptor.addInnerInterceptor(paginationInnerInterceptor);
return interceptor;
}
}
至此,问题解决,删除最后一页最后一条数据后,页面能够正确显示结果。