MyBatis 分页功能是有所欠缺的,需要手动也分页SQL实现;当然也不是不可以解决,比如使用插件就可以很好的解决这个
先了解下 Mybatis
的 Mapper
执行过程: 我们通过映射器 Mapper
对数据库进行增删改操作时,Mapper
执行的过程是通过 Executor
、StatementHandler
、ParameterHandler
和ResultHandler
来完成对数据库的操作和返回结果
- Executor 代表执行器,由它来调度StatementHandler、ParameterHandler、ResultHandler等来执行对应的SQL。
- StatementHandler 的作用是使用数据库的Statement(PreparedStatement) 执行操作,是上面提到的四个对象的核心。
- ParameterHandler 用于SQL对参数的处理。
- ResultHandler是进行最后数据集(ResultSet)的封装返回处理的。
前提
MyBatis
拦截器知识介绍
public interface Interceptor {
Object intercept(Invocation var1) throws Throwable;
Object plugin(Object var1);
void setProperties(Properties var1);
}
- intercept方法是插件的核心方法,它有个Invocation类型的参数,通过这个参数可以反射调度原来对象的方法。
- plugin方法的作用是给被拦截的对象生成一个代理对象并返回。
- setProperties方法允许在plugin元素中配置所需参数。
分页拦截器
思路:在Mapper 方法中传入Page分页对象,在拦截器中根据是否有分页Page对象来判断是否进行分页
Page对象类
public class Pagination<T> {
// 开始页(当前页)
private int startPage;
// 每页的记录数
private int pageSize;
// 总记录数
private int totalRecord;
// 总页数
private int totalPage;
// 每页的数据集合
private List<T> content;
public Pagination() {
super();
}
public Pagination(int startPage, int pageSize) {
super();
this.startPage = startPage;
this.pageSize = pageSize;
}
public Pagination(int startPage, int pageSize, int totalRecord, List<T> content) {
super();
this.startPage = startPage;
this.pageSize = pageSize;
this.totalRecord = totalRecord;
this.content = content;
this.totalPage = this.totalRecord > 0 && this.pageSize > 0 ? (this.totalRecord % this.pageSize == 0 ? this.totalRecord / this.pageSize: this.totalRecord / this.pageSize + 1) : 0;
}
public int getStartPage() {
return startPage;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public int getTotalRecord() {
return totalRecord;
}
public void setTotalRecord(int totalRecord) {
this.totalPage = this.totalRecord > 0 && this.pageSize > 0 ? (this.totalRecord % this.pageSize == 0 ? this.totalRecord / this.pageSize: this.totalRecord / this.pageSize + 1) : 0;
this.totalRecord = totalRecord;
}
public int getTotalPage() {
return totalPage;
}
public List<T> getContent() {
return content;
}
public void setContent(List<T> content) {
this.content = content;
}
}
Dialect 方言类
不同的数据库分页的SQL语句是不一样的,这里使用方言的形式来支持不同的数据库,只需要在配置拦截器的时候配置一个dialect参数即可
Dialect接口
public interface Dialect {