mybatis-config.xml
page
import java.util.ArrayList;
import java.util.List;
import org.apache.ibatis.session.RowBounds;
/**
* Mybatis - 分页对象
*
* @author liuzh/abel533/isea533
* @version 3.2.1
* @url http://git.oschina.net/free/Mybatis_PageHelper
*/
public class Page extends ArrayList {
/**
* 不进行count查询
*/
public static final int NO_SQL_COUNT = -1;
public static final int SQL_COUNT = 0;
private int pageNum;
private int pageSize;
private int startRow;
private int endRow;
private long total;
private int pages;
public Page(int pageNum, int pageSize) {
this(pageNum, pageSize, SQL_COUNT);
}
public Page(int pageNum, int pageSize, int total) {
super(pageSize);
this.pageNum = pageNum;
this.pageSize = pageSize;
this.total = total;
this.startRow = pageNum > 0 ? (pageNum - 1) * pageSize : 0;
this.endRow = pageNum * pageSize;
}
public Page(RowBounds rowBounds, int total) {
super(rowBounds.getLimit());
this.pageSize = rowBounds.getLimit();
this.startRow = rowBounds.getOffset();
//RowBounds方式默认不求count总数,如果想求count,可以修改这里为SQL_COUNT
this.total = total;
this.endRow = this.startRow + this.pageSize;
}
public List getResult() {
return this;
}
public int getPages() {
return pages;
}
public void setPages(int pages) {
this.pages = pages;
}
public int getEndRow() {
return endRow;
}
public void setEndRow(int endRow) {
this.endRow = endRow;
}
public int getPageNum() {
return pageNum;
}
public void setPageNum(int pageNum) {
this.pageNum = pageNum;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public int getStartRow() {
return startRow;
}
public void setStartRow(int startRow) {
this.startRow = startRow;
}
public long getTotal() {
return total;
}
public void setTotal(long total) {
this.total = total;
}
@Override
public String toString() {
return "Page{" +
"pageNum=" + pageNum +
", pageSize=" + pageSize +
", startRow=" + startRow +
", endRow=" + endRow +
", total=" + total +
", pages=" + pages +
'}';
}
}
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ResultMap;
import org.apache.ibatis.mapping.ResultMapping;
import org.apache.ibatis.mapping.SqlSource;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
@Intercepts(@Signature(type = Executor.class, method = "query", args = {
MappedStatement.class, Object.class, RowBounds.class,
ResultHandler.class }))
public class PageHelper implements Interceptor {
private static final ThreadLocal localPage = new ThreadLocal();
private static final List EMPTY_RESULTMAPPING = new ArrayList(
0);
// 数据库方言
private static String dialect = "";
// RowBounds参数offset作为PageNum使用 - 默认不使用
private static boolean offsetAsPageNum = false;
// RowBounds是否进行count查询 - 默认不查询
private static boolean rowBoundsWithCount = false;
/**
* 开始分页
*
* @param pageNum
* @param pageSize
*/
public static void startPage(int pageNum, int pageSize) {
startPage(pageNum, pageSize, true);
}
/**
* 开始分页
*
* @param pageNum
* @param pageSize
*/
public static void startPage(int pageNum, int pageSize, boolean count) {
localPage.set(new Page(pageNum, pageSize, count ? Page.SQL_COUNT
: Page.NO_SQL_COUNT));
}
@Override
public Object intercept(Invocation invocation) throws Throwable {
System.out.println("page");
final Object[] args = invocation.getArgs();
RowBounds rowBounds = (RowBounds) args[2];
if (localPage.get() == null && rowBounds == RowBounds.DEFAULT) {
return invocation.proceed();
} else {
// 忽略RowBounds-否则会进行Mybatis自带的内存分页
args[2] = RowBounds.DEFAULT;
MappedStatement ms = (MappedStatement) args[0];
Object parameterObject = args[1];
BoundSql boundSql = ms.getBoundSql(parameterObject);
// 分页信息
Page page = localPage.get();
// 移除本地变量
localPage.remove();
if (page == null) {
if (offsetAsPageNum) {
page = new Page(rowBounds.getOffset(),
rowBounds.getLimit(),
rowBoundsWithCount ? Page.SQL_COUNT
: Page.NO_SQL_COUNT);
} else {
page = new Page(rowBounds,
rowBoundsWithCount ? Page.SQL_COUNT
: Page.NO_SQL_COUNT);
}
}
MappedStatement qs = newMappedStatement(ms, new BoundSqlSqlSource(
boundSql));
// 将参数中的MappedStatement替换为新的qs,防止并发异常
args[0] = qs;
MetaObject msObject = SystemMetaObject.forObject(qs);
String sql = (String) msObject.getValue("sqlSource.boundSql.sql");
// 简单的通过total的值来判断是否进行count查询
if (page.getTotal() > Page.NO_SQL_COUNT) {
// 求count - 重写sql
msObject.setValue("sqlSource.boundSql.sql", getCountSql(sql));
// 查询总数
Object result = invocation.proceed();
int totalCount = (Integer) ((List) result).get(0);
page.setTotal(totalCount);
int totalPage = totalCount / page.getPageSize()
+ ((totalCount % page.getPageSize() == 0) ? 0 : 1);
page.setPages(totalPage);
// 分页sql - 重写sql
msObject.setValue("sqlSource.boundSql.sql",
getPageSql(sql, page));
// 恢复类型
msObject.setValue("resultMaps", ms.getResultMaps());
// 执行分页查询
result = invocation.proceed();
// 得到处理结果
page.addAll((List) result);
// 返回结果
return page;
} else {
// 分页sql - 重写sql
msObject.setValue("sqlSource.boundSql.sql",
getPageSql(sql, page));
// 恢复类型
msObject.setValue("resultMaps", ms.getResultMaps());
// 执行分页查询
Object result = invocation.proceed();
// 得到处理结果
page.addAll((List) result);
// 返回结果
return page;
}
}
}
/**
* 获取总数sql - 如果要支持其他数据库,修改这里就可以
*
* @param sql
* @return
*/
private String getCountSql(String sql) {
return "select count(0) from (" + sql + ") tmp_count";
}
/**
* 获取分页sql - 如果要支持其他数据库,修改这里就可以
*
* @param sql
* @param page
* @return
*/
private String getPageSql(String sql, Page page) {
StringBuilder pageSql = new StringBuilder(200);
if("postgresql".equals(dialect)) {
pageSql.append(sql);
pageSql.append(" limit " + page.getPageSize() + " offset "
+ page.getStartRow());
} else if ("mysql".equals(dialect)) {
pageSql.append(sql);
pageSql.append(" limit " + page.getStartRow() + ","
+ page.getPageSize());
} else if ("hsqldb".equals(dialect)) {
pageSql.append(sql);
pageSql.append(" LIMIT " + page.getPageSize() + " OFFSET "
+ page.getStartRow());
} else if ("oracle".equals(dialect)) {
pageSql.append("select * from ( select temp.*, rownum row_id from ( ");
pageSql.append(sql);
pageSql.append(" ) temp where rownum <= ").append(page.getEndRow());
pageSql.append(") where row_id > ").append(page.getStartRow());
}
return pageSql.toString();
}
private class BoundSqlSqlSource implements SqlSource {
BoundSql boundSql;
public BoundSqlSqlSource(BoundSql boundSql) {
this.boundSql = boundSql;
}
public BoundSql getBoundSql(Object parameterObject) {
return boundSql;
}
}
/**
* 由于MappedStatement是一个全局共享的对象,因而需要复制一个对象来进行操作,防止并发访问导致错误
*
* @param ms
* @param newSqlSource
* @return
*/
private MappedStatement newMappedStatement(MappedStatement ms,
SqlSource newSqlSource) {
MappedStatement.Builder builder = new MappedStatement.Builder(
ms.getConfiguration(), ms.getId() + "_分页", newSqlSource,
ms.getSqlCommandType());
builder.resource(ms.getResource());
builder.fetchSize(ms.getFetchSize());
builder.statementType(ms.getStatementType());
builder.keyGenerator(ms.getKeyGenerator());
if (ms.getKeyProperties() != null && ms.getKeyProperties().length != 0) {
StringBuffer keyProperties = new StringBuffer();
for (String keyProperty : ms.getKeyProperties()) {
keyProperties.append(keyProperty).append(",");
}
keyProperties.delete(keyProperties.length() - 1,
keyProperties.length());
builder.keyProperty(keyProperties.toString());
}
builder.timeout(ms.getTimeout());
builder.parameterMap(ms.getParameterMap());
// 由于resultMaps第一次需要返回int类型的结果,所以这里需要生成一个resultMap - 防止并发错误
List resultMaps = new ArrayList();
ResultMap resultMap = new ResultMap.Builder(ms.getConfiguration(),
ms.getId(), int.class, EMPTY_RESULTMAPPING).build();
resultMaps.add(resultMap);
builder.resultMaps(resultMaps);
builder.resultSetType(ms.getResultSetType());
builder.cache(ms.getCache());
builder.flushCacheRequired(ms.isFlushCacheRequired());
builder.useCache(ms.isUseCache());
return builder.build();
}
/**
* 只拦截Executor
*
* @param target
* @return
*/
@Override
public Object plugin(Object target) {
if (target instanceof Executor) {
return Plugin.wrap(target, this);
} else {
return target;
}
}
public void setProperties(Properties p) {
dialect = p.getProperty("dialect");
if (dialect == null || dialect.equals("")) {
throw new RuntimeException("Mybatis分页插件PageHelper无法获取dialect参数!");
}
// offset作为PageNum使用
String offset = p.getProperty("offsetAsPageNum");
if (offset != null && offset.toUpperCase().equals("TRUE")) {
offsetAsPageNum = true;
}
// RowBounds方式是否做count查询
String withcount = p.getProperty("rowBoundsWithCount");
if (withcount != null && withcount.toUpperCase().equals("TRUE")) {
rowBoundsWithCount = true;
}
}
}
用法:
public String getUserList(HttpServletRequest request) {
String json = "";
try {
String page = request.getParameter("page");
String rows = request.getParameter("rows");
// 开始分页
PageHelper.startPage(Integer.parseInt(page), Integer.parseInt(rows));
List