若依源码解析:pagehelper和mybaties进行分页
若依分页使用示例
@PreAuthorize("@ss.hasPermi('system:dict:list')")
@GetMapping("/list")
public TableDataInfo list(SysDictData dictData)
{
startPage();
List<SysDictData> list = dictDataService.selectDictDataList(dictData);
return getDataTable(list);
}
startPage()方法介绍
在BaseController中有一个startPage()方法用于设置请求分页数据
/**
* 设置请求分页数据
*/
protected void startPage()
{
PageDomain pageDomain = TableSupport.buildPageRequest();
Integer pageNum = pageDomain.getPageNum();
Integer pageSize = pageDomain.getPageSize();
if (StringUtils.isNotNull(pageNum) && StringUtils.isNotNull(pageSize))
{
String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
Boolean reasonable = pageDomain.getReasonable();
PageHelper.startPage(pageNum, pageSize, orderBy).setReasonable(reasonable);
}
}
PageHelper.startPage方法介绍
setLocalPage是将page保存到本地线程变量里面。
/**
* 开始分页
*
* @param pageNum 页码
* @param pageSize 每页显示数量
* @param orderBy 排序
*/
public static <E> Page<E> startPage(int pageNum, int pageSize, String orderBy) {
Page<E> page = startPage(pageNum, pageSize);
page.setOrderBy(orderBy);
return page;
}
···
/**
* 开始分页
*
* @param pageNum 页码
* @param pageSize 每页显示数量
* @param count 是否进行count查询
* @param reasonable 分页合理化,null时用默认配置
* @param pageSizeZero true且pageSize=0时返回全部结果,false时分页,null时用默认配置
*/
public static <E> Page<E> startPage(int pageNum, int pageSize, boolean count, Boolean reasonable, Boolean pageSizeZero) {
Page<E> page = new Page<E>(pageNum, pageSize, count);
page.setReasonable(reasonable);
page.setPageSizeZero(pageSizeZero);
//当已经执行过orderBy的时候
Page<E> oldPage = getLocalPage();
if (oldPage != null && oldPage.isOrderByOnly()) {
page.setOrderBy(oldPage.getOrderBy());
}
setLocalPage(page);
return page;
}
封装分页对象
TableSupport.buildPageRequest()来将前台传递过来的分页信息记录下来封装分页对象
/**
* 表格数据处理
*
* @author ruoyi
*/
public class TableSupport
{
/**
* 当前记录起始索引
*/
public static final String PAGE_NUM = "pageNum";
/**
* 每页显示记录数
*/
public static final String PAGE_SIZE = "pageSize";
/**
* 排序列
*/
public static final String ORDER_BY_COLUMN = "orderByColumn";
/**
* 排序的方向 "desc" 或者 "asc".
*/
public static final String IS_ASC = "isAsc";
/**
* 分页参数合理化
*/
public static final String REASONABLE = "reasonable";
/**
* 封装分页对象
*/
public static PageDomain getPageDomain()
{
PageDomain pageDomain = new PageDomain();
pageDomain.setPageNum(ServletUtils.getParameterToInt(PAGE_NUM));
pageDomain.setPageSize(ServletUtils.getParameterToInt(PAGE_SIZE));
pageDomain.setOrderByColumn(ServletUtils.getParameter(ORDER_BY_COLUMN));
pageDomain.setIsAsc(ServletUtils.getParameter(IS_ASC));
pageDomain.setReasonable(ServletUtils.getParameterToBool(REASONABLE));
return pageDomain;
}
public static PageDomain buildPageRequest()
{
return getPageDomain();
}
}
com.github.pagehelper介绍
com.github.pagehelper 是一个基于 MyBatis 的分页插件,它能够简化在数据库查询中使用分页功能的操作。
- 在查询方法中使用分页:在需要进行分页查询的方法中,使用 PageHelper.startPage 方法来开启分页功能。示例代码如下:
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
public List<MyEntity> queryEntities(int pageNum, int pageSize) {
PageHelper.startPage(pageNum, pageSize);
List<MyEntity> entities = yourMapper.queryEntities();
PageInfo<MyEntity> pageInfo = new PageInfo<>(entities);
return pageInfo.getList();
}
在上述示例中,pageNum
表示页码,pageSize
表示每页的数据条数。通过调用 PageHelper.startPage(pageNum, pageSize)
方法,会将当前线程绑定一个分页参数对象,这样在查询方法执行时,PageHelper 会自动对查询语句进行拦截并进行分页处理。
- 获取分页结果:使用 PageInfo 类可以获取到分页查询的详细信息,如总记录数、总页数等。在上述示例中,通过创建 PageInfo 对象并传入查询结果集,然后通过
pageInfo.getList()
方法获取分页后的数据列表。
这样,你就可以在使用 com.github.pagehelper 进行分页查询时,简化代码的编写,并且自动处理分页的逻辑。
请注意,以上只是一个基本的使用示例,你可以根据自己的具体需求进行更多的配置和使用方式。另外,确保你选择的 com.github.pagehelper 版本与你项目中使用的 MyBatis 版本兼容。你可以在 com.github.pagehelper 的 GitHub 页面上查找更多的文档和示例代码。
集成和使用 com.github.pagehelper
如果你使用 Spring Boot 和 MyBatis-Plus(一种基于 MyBatis 的数据库操作框架),你可以按照以下步骤来集成和使用 com.github.pagehelper:
- 添加依赖:在你的 Spring Boot 项目中,打开
pom.xml
文件,并添加以下依赖:
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>最新版本号</version>
</dependency>
- 配置文件:在
application.properties
(或application.yml
)中添加 PageHelper 的相关配置。示例配置如下:
# PageHelper 配置
pagehelper.helper-dialect=your-database-dialect
pagehelper.reasonable=true
pagehelper.support-methods-arguments=true
其中,your-database-dialect
是你所使用的数据库方言,例如 "mysql"、"oracle" 等。
- 分页查询:在你的 Mapper 接口中,可以直接使用 MyBatis-Plus 提供的查询方法来实现分页查询。示例代码如下:
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yourpackage.entity.MyEntity;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface MyEntityMapper extends BaseMapper<MyEntity> {
Page<MyEntity> queryEntities(Page<MyEntity> page);
}
在上述示例中,Page
类型是 com.baomidou.mybatisplus.extension.plugins.pagination 包下的分页对象,通过传入分页参数来进行分页查询。
- 服务层调用:在你的服务层(Service)中,调用 Mapper 接口中的分页查询方法,并传入分页参数。示例代码如下:
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yourpackage.entity.MyEntity;
import com.yourpackage.mapper.MyEntityMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class MyEntityService {
private final MyEntityMapper myEntityMapper;
@Autowired
public MyEntityService(MyEntityMapper myEntityMapper) {
this.myEntityMapper = myEntityMapper;
}
public Page<MyEntity> queryEntities(int pageNum, int pageSize) {
Page<MyEntity> page = new Page<>(pageNum, pageSize);
return myEntityMapper.queryEntities(page);
}
}
在上述示例中,通过创建一个 Page
对象,并传入页码和每页数据条数,然后调用 Mapper 接口的分页查询方法。
这样,你就可以在使用 Spring Boot 和 MyBatis-Plus 的项目中,集成和使用 com.github.pagehelper 来实现分页查询功能。请注意,确保你选择的 com.github.pagehelper 版本与 MyBatis-Plus 版本兼容。
PageInterceptor进行拦截并执行分页sql
com.github.pagehelper.PageInterceptor这个类就实现了mybaties的interceptor接口,调用其中的intercept方法。
@Override
public Object intercept(Invocation invocation) throws Throwable {
try {
Object[] args = invocation.getArgs();
MappedStatement ms = (MappedStatement) args[0];
Object parameter = args[1];
RowBounds rowBounds = (RowBounds) args[2];
ResultHandler resultHandler = (ResultHandler) args[3];
Executor executor = (Executor) invocation.getTarget();
CacheKey cacheKey;
BoundSql boundSql;
//由于逻辑关系,只会进入一次
if (args.length == 4) {
//4 个参数时
boundSql = ms.getBoundSql(parameter);
cacheKey = executor.createCacheKey(ms, parameter, rowBounds, boundSql);
} else {
//6 个参数时
cacheKey = (CacheKey) args[4];
boundSql = (BoundSql) args[5];
}
checkDialectExists();
List resultList;
//调用方法判断是否需要进行分页,如果不需要,直接返回结果
if (!dialect.skip(ms, parameter, rowBounds)) {
//判断是否需要进行 count 查询
if (dialect.beforeCount(ms, parameter, rowBounds)) {
//查询总数
Long count = count(executor, ms, parameter, rowBounds, resultHandler, boundSql);
//处理查询总数,返回 true 时继续分页查询,false 时直接返回
if (!dialect.afterCount(count, parameter, rowBounds)) {
//当查询总数为 0 时,直接返回空的结果
return dialect.afterPage(new ArrayList(), parameter, rowBounds);
}
}
resultList = ExecutorUtil.pageQuery(dialect, executor,
ms, parameter, rowBounds, resultHandler, boundSql, cacheKey);
} else {
//rowBounds用参数值,不使用分页插件处理时,仍然支持默认的内存分页
resultList = executor.query(ms, parameter, rowBounds, resultHandler, cacheKey, boundSql);
}
return dialect.afterPage(resultList, parameter, rowBounds);
} finally {
if(dialect != null){
dialect.afterAll();//这里将销毁threadlocal
}
}
}