1.问题来源
我们使用SpringMVC的时候,我们每个Controller都有一个获取分页数据的方法,但是被调用的Service实现了"
extends IService<实体类>
"的接口,因此分页信息"Page<实体类>
"和查询条件都需要在Controller中进行组合,或者是在Controller和Service中间再添加一层,这样会对文件功能或项目结构造成破坏,于是我们需要自定义一个分页方法,并将"Page<实体类>"和查询条件都在Service层进行编写,于是出现了第二个问题,非特殊情况下除了查询条件,其他的代码都是一摸一样的,每次进行分页查询都需要编写大量的重复代码,这无疑增加了开发的复杂性和维护成本。为了解决这一问题,本文将介绍如何使用MyBatis-Plus实现一个通用的分页查询封装类,以简化分页查询的开发过程。
2.解决方案
1. 实现一个公共的分页处理类:PageHandler.java,实现多种分页方法和其他辅助方法。
2. 需要分页的Service实例化这个类
3. 组合查询条件,并调用PageHandler类中的分页方法即可
3.实现
MyBatis-plus的插件引入可以查看《SpringBoot入门二十八,添加MyBatis-Plus支持》第5部分:分页插件
3.1 分页处理类
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
/**
* MyBatis-plus分页封装类,简化分页操作,格式化返回数据
*/
@Component
public class PageHandler<T> {
private static String PAGE_NO = "pageNo";
private static String PAGE_SIZE = "pageSize";
/**
* 功能:无条件分页查询
*
* @param baseMapper 指定的查询接口
* @param pageNum 当前页页码
* @param pageSize 页面显示条数
*
* @return Map<String, Object>
*/
public Map<String, Object> pageList(BaseMapper<T> baseMapper, int pageNum, int pageSize) {
return pageList(baseMapper, Wrappers.emptyWrapper(), pageNum, pageSize);
}
/**
* 功能:翻页查询
*
* @param baseMapper 指定的查询接口
* @param queryWrapper 实体对象封装操作类
* @param pageNum 当前页页码
* @param pageSize 页面显示条数
*
* @return Map<String, Object>
*/
public Map<String, Object> pageList(BaseMapper<T> baseMapper, Wrapper<T> queryWrapper, int pageNum, int pageSize) {
// 创建分页对象,指定当前页和每页显示的记录数
Page<T> page = new Page<>(pageNum, pageSize);
// 执行带条件的分页查询
page = baseMapper.selectPage(page, queryWrapper);
return buildPageResult(page);
}
/**
* 功能:无条件分页查询
*
* @param baseMapper 指定的查询接口
* @param request 当前页页码
*
* @return Map<String, Object>
*/
public Map<String, Object> pageList(BaseMapper<T> baseMapper, HttpServletRequest request) {
return pageList(baseMapper, Wrappers.emptyWrapper(), request);
}
/**
* 功能:翻页查询
*
* @param baseMapper 指定的查询接口
* @param queryWrapper 实体对象封装操作类
* @param request 当前页页码
*
* @return Map<String, Object>
*/
public Map<String, Object> pageList(BaseMapper<T> baseMapper, Wrapper<T> queryWrapper, HttpServletRequest request) {
// 创建分页对象,获取分页信息
Page<T> page = getPage(request);
// 执行带条件的分页查询
page = baseMapper.selectPage(page, queryWrapper);
return buildPageResult(page);
}
/**
* 功能:根据请求获取分页对象 该方法从HTTP请求中提取分页参数,并根据这些参数创建一个分页对象
* 主要目的是为了简化分页查询的处理过程,将分页相关的逻辑封装到一个方法中
*
* @param request HTTP请求对象,用于获取分页参数
*
* @return 返回一个分页对象,该对象包含了当前页码和每页大小
*/
public Page<T> getPage(HttpServletRequest request) {
// 从URL中获取page参数
String pageNo = request.getParameter(PAGE_NO);
// 从URL中获取limit参数
String pageSize = request.getParameter(PAGE_SIZE);
// 将参数转换为长整数(注意:这里应该添加异常处理,以防参数不是有效的长整数)
long current = ObjectUtils.isEmpty(pageNo) ? 1L : Long.parseLong(pageNo); // 默认为第1页
long size = ObjectUtils.isEmpty(pageSize) ? 10L : Long.parseLong(pageSize); // 默认为每页10条
Page<T> page = new Page<>(current, size);
return page;
}
/**
* 功能:构建分页查询结果
*
* 该方法用于将MyBatis-Plus的Page对象转换为一个包含分页信息和数据的Map对象 主要用于接口返回,以便前端可以获取到分页查询的相关信息和数据
*
* @param page MyBatis-Plus的Page对象,包含了分页查询的结果和分页信息
*
* @return 返回一个Map对象,包含了分页码、总记录数、每页记录数和数据列表
*/
public Map<String, Object> buildPageResult(Page<T> page) {
Map<String, Object> map = new HashMap<String, Object>();
map.put("code", 0);
map.put("count", page.getTotal());
map.put("page_count", page.getPages());
map.put("data", page.getRecords());
return map;
}
}
3.2 调用
可以直接new工具类对象,也可以通过注入方式
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qfx.modules.common.handler.PageHandler;
import com.qfx.modules.system.dao.SysUserDao;
import com.qfx.modules.system.entity.SysUser;
import com.qfx.modules.system.service.SysUserSer;
@Service
public class SysUserSerImpl extends ServiceImpl<SysUserDao, SysUser> implements SysUserSer {
@Autowired
private HttpServletRequest request;
@Autowired
private PageHandler<SysUser> pageHandler;
@Autowired
private SysUserDao sysUserDao;
@Override
public Map<String, Object> page(SysUser sysUser) {
// 方式一,使用QueryWrapper
// 将user_name设置为like条件,其他sysUser对象参数eq条件
// QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
// if (!ObjectUtils.isEmpty(sysUser.getUserName())) {
// queryWrapper.like("user_name", sysUser.getUserName());
// sysUser.setUserName(null);
// }
// queryWrapper.setEntity(sysUser);
// 方式二,使用LambdaQueryWrapper(推荐)
// 将user_name设置为like条件,其他sysUser对象参数eq条件
LambdaQueryWrapper<SysUser> lambdaQueryWrapper = new LambdaQueryWrapper<>();
if (!ObjectUtils.isEmpty(sysUser.getUserName())) {
lambdaQueryWrapper.like(SysUser::getUserName, sysUser.getUserName());
sysUser.setUserName(null);
}
lambdaQueryWrapper.setEntity(sysUser);
return pageHandler.pageList(baseMapper, lambdaQueryWrapper, request);
}
}
核心代码:
pageHandler.pageList(baseMapper, lambdaQueryWrapper, request);
第一个参数
baseMapper是固定写法:com.baomidou.mybatisplus.extension.service.impl.ServiceImpl.baseMapper
4.自定义sql分页
4.1 xxxMapper.java编写接口方法
必须类型必须是:
Page<实体类>
格式
import org.springframework.stereotype.Repository;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qfx.modules.system.entity.SysUser;
@Repository
public interface SysUserDao extends BaseMapper<SysUser> {
/**
* 自定义分页查询
* @param page MyBatis-plus分页插件信息
* @return IPage<SysUser>
*/
Page<SysUser> selectList(Page<SysUser> page, SysUser sysUser);
}
4.2 调用
调用方式基本一致,只不过是要将对应的xxxMapper接口实例化,建议通过注入方式实现,同样需要实例化pageHandler类
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qfx.modules.common.handler.PageHandler;
import com.qfx.modules.system.dao.SysUserDao;
import com.qfx.modules.system.entity.SysUser;
import com.qfx.modules.system.service.SysUserSer;
@Service
public class SysUserSerImpl extends ServiceImpl<SysUserDao, SysUser> implements SysUserSer {
@Autowired
private HttpServletRequest request;
@Autowired
private PageHandler<SysUser> pageHandler;
@Autowired
private SysUserDao sysUserDao;
@Override
public Map<String, Object> pageExtTwo(SysUser sysUser) {
// 获取分页对象
Page<SysUser> page = pageHandler.getPage(request);
// 调用自定义分页查询方法
page = sysUserDao.selectList(page, sysUser);
// 构建分页查询结果
return pageHandler.buildPageResult(page);
}
}