原文地址:http://blog.csdn.net/isea533/article/details/23831273
分页插件示例:http://blog.csdn.net/isea533/article/details/24700339
最新版分页插件:http://blog.csdn.net/isea533/article/details/25505413
项目地址:http://git.oschina.net/free/Mybatis_PageHelper
 
以前为Mybatis分页查询发愁过,而且在网上搜过很多相关的文章,最后一个都没采用。在分页的地方完全都是手写分页SQL和count的sql,总之很麻烦。
后来有一段时间想从Mybatis内部写一个分页的实现,我对LanguageDriver写过一个实现,自动分页是没问题了,但是查询总数(count)仍然没法一次性解决,最后不了了之。
最近又要用到分页,为了方便必须地写个通用的分页类,因此又再次参考网上大多数的Mybatis分页代码,本插件主要参考自:
http://blog.csdn.net/hupanfeng/article/details/9265341
实际上在很早之前,有人在github上开源过一个实现,支持mysql,oracle,sqlserver的,和上面这个参考的比较类似,考虑的
更全面。但是我觉得太多类太麻烦了,所以自己实现了一个只有一个拦截器的类,实际上可以分为两个类,其中一个类被我写成静态类放在了拦截器中,你也可以将
Page类提取出来,方便使用Page。
先说实现方法,该插件只有一个类:PageHelper.java
拦截器签名为:
- @Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class}),  
-         @Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class})})  
 
这里的签名对整个实现和思想至关重要,首先我拦截prepare方法来改分页SQL,来做count查询。然后我拦截handleResultSets方法来获取最后的处理结果,将结果放到Page对象中。
下面是修改分页的代码,是针对Oracle数据进行的修改,如果有用其他数据库的,自己修改这里的代码就可以。
-     private String buildPageSql(String sql, Page page) {  
-         StringBuilder pageSql = new StringBuilder(200);  
-         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();  
-     }  
 
之后在下面的setPageParameter方法中一个selelct count语句,这里也需要根据数据库类型进行修改:
-         String countSql = "select count(0) from (" + sql + ")";  
 
为什么我不提供对各种数据库的支持呢,我觉得没必要,还有些数据库不支持分页,而且这个插件越简单对使用的开发人员来说越容易理解,越容易修改。修改成自己需要的分页查询肯定不是问题。
最后上完整代码(继续看下去,下面还有使用方法):(点击下载)
- package com.mybatis.util;  
-   
- import org.apache.ibatis.executor.parameter.ParameterHandler;  
- import org.apache.ibatis.executor.resultset.ResultSetHandler;  
- import org.apache.ibatis.executor.statement.StatementHandler;  
- import org.apache.ibatis.mapping.BoundSql;  
- import org.apache.ibatis.mapping.MappedStatement;  
- import org.apache.ibatis.plugin.*;  
- import org.apache.ibatis.reflection.MetaObject;  
- import org.apache.ibatis.reflection.SystemMetaObject;  
- import org.apache.ibatis.scripting.defaults.DefaultParameterHandler;  
- import org.apache.log4j.Logger;  
-   
- import java.sql.*;  
- import java.util.List;  
- import java.util.Properties;  
-   
- @Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class}),  
-         @Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class})})  
- public class PageHelper implements Interceptor {  
-     private static final Logger logger = Logger.getLogger(PageHelper.class);  
-   
-     public static final ThreadLocal<Page> localPage = new ThreadLocal<Page>();  
-   
-     
-     public static void startPage(int pageNum, int pageSize) {  
-         localPage.set(new Page(pageNum, pageSize));  
-     }  
-   
-     
-     public static Page endPage() {  
-         Page page = localPage.get();  
-         localPage.remove();  
-         return page;  
-     }  
-   
-     @Override  
-     public Object intercept(Invocation invocation) throws Throwable {  
-         if (localPage.get() == null) {  
-             return invocation.proceed();  
-         }  
-         if (invocation.getTarget() instanceof StatementHandler) {  
-             StatementHandler statementHandler = (StatementHandler) invocation.getTarget();  
-             MetaObject metaStatementHandler = SystemMetaObject.forObject(statementHandler);  
-             
-             
-             while (metaStatementHandler.hasGetter("h")) {  
-                 Object object = metaStatementHandler.getValue("h");  
-                 metaStatementHandler = SystemMetaObject.forObject(object);  
-             }  
-             
-             while (metaStatementHandler.hasGetter("target")) {  
-                 Object object = metaStatementHandler.getValue("target");  
-                 metaStatementHandler = SystemMetaObject.forObject(object);  
-             }  
-             MappedStatement mappedStatement = (MappedStatement) metaStatementHandler.getValue("delegate.mappedStatement");  
-             
-             Page page = localPage.get();  
-             BoundSql boundSql = (BoundSql) metaStatementHandler.getValue("delegate.boundSql");  
-             
-             String sql = boundSql.getSql();  
-             
-             String pageSql = buildPageSql(sql, page);  
-             
-             metaStatementHandler.setValue("delegate.boundSql.sql", pageSql);  
-             Connection connection = (Connection) invocation.getArgs()[0];  
-             
-             setPageParameter(sql, connection, mappedStatement, boundSql, page);  
-             
-             return invocation.proceed();  
-         } else if (invocation.getTarget() instanceof ResultSetHandler) {  
-             Object result = invocation.proceed();  
-             Page page = localPage.get();  
-             page.setResult((List) result);  
-             return result;  
-         }  
-         return null;  
-     }  
-   
-     
-     @Override  
-     public Object plugin(Object target) {  
-         if (target instanceof StatementHandler || target instanceof ResultSetHandler) {  
-             return Plugin.wrap(target, this);  
-         } else {  
-             return target;  
-         }  
-     }  
-   
-     @Override  
-     public void setProperties(Properties properties) {  
-   
-     }  
-   
-     
-     private String buildPageSql(String sql, Page page) {  
-         StringBuilder pageSql = new StringBuilder(200);  
-         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 void setPageParameter(String sql, Connection connection, MappedStatement mappedStatement,  
-                                   BoundSql boundSql, Page page) {  
-         
-         String countSql = "select count(0) from (" + sql + ")";  
-         PreparedStatement countStmt = null;  
-         ResultSet rs = null;  
-         try {  
-             countStmt = connection.prepareStatement(countSql);  
-             BoundSql countBS = new BoundSql(mappedStatement.getConfiguration(), countSql,  
-                     boundSql.getParameterMappings(), boundSql.getParameterObject());  
-             setParameters(countStmt, mappedStatement, countBS, boundSql.getParameterObject());  
-             rs = countStmt.executeQuery();  
-             int totalCount = 0;  
-             if (rs.next()) {  
-                 totalCount = rs.getInt(1);  
-             }  
-             page.setTotal(totalCount);  
-             int totalPage = totalCount / page.getPageSize() + ((totalCount % page.getPageSize() == 0) ? 0 : 1);  
-             page.setPages(totalPage);  
-         } catch (SQLException e) {  
-             logger.error("Ignore this exception", e);  
-         } finally {  
-             try {  
-                 rs.close();  
-             } catch (SQLException e) {  
-                 logger.error("Ignore this exception", e);  
-             }  
-             try {  
-                 countStmt.close();  
-             } catch (SQLException e) {  
-                 logger.error("Ignore this exception", e);  
-             }  
-         }  
-     }  
-   
-     
-     private void setParameters(PreparedStatement ps, MappedStatement mappedStatement, BoundSql boundSql,  
-                                Object parameterObject) throws SQLException {  
-         ParameterHandler parameterHandler = new DefaultParameterHandler(mappedStatement, parameterObject, boundSql);  
-         parameterHandler.setParameters(ps);  
-     }  
-   
-     
-     public static class Page<E> {  
-         private int pageNum;  
-         private int pageSize;  
-         private int startRow;  
-         private int endRow;  
-         private long total;  
-         private int pages;  
-         private List<E> result;  
-   
-         public Page(int pageNum, int pageSize) {  
-             this.pageNum = pageNum;  
-             this.pageSize = pageSize;  
-             this.startRow = pageNum > 0 ? (pageNum - 1) * pageSize : 0;  
-             this.endRow = pageNum * pageSize;  
-         }  
-   
-         public List<E> getResult() {  
-             return result;  
-         }  
-   
-         public void setResult(List<E> result) {  
-             this.result = result;  
-         }  
-   
-         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 +  
-                     ‘}‘;  
-         }  
-     }  
- }  
 
使用该拦截器首先需要在Mybatis配置中配置该拦截器:
- <plugins>  
-     <plugin interceptor="com.mybatis.util.PageHelper"></plugin>  
- </plugins>  
 
配置拦截器的时候需要注意plugins的位置,plugins位置顺序如下:
- properties?, settings?, typeAliases?, typeHandlers?, objectFactory?, objectWrapperFactory?, plugins?, environments?, databaseIdProvider?, mappers?  
 
最后是调用该方法的例子代码(Service层):
- @Override  
- public PageHelper.Page<SysLoginLog> findSysLoginLog(String loginIp,  
-                                          String username,  
-                                          String loginDate,  
-                                          String exitDate,  
-                                          String logerr,  
-                                          int pageNumber,  
-                                          int pageSize) throws BusinessException {  
-     PageHelper.startPage(pageNumber,pageSize);  
-     sysLoginLogMapper.findSysLoginLog(loginIp, username, loginDate, exitDate, logerr);  
-     return PageHelper.endPage();  
- }  
 
 
从上面可以看到使用该插件使用起来是很简单的,只需要在查询前后使用PageHelper的startPage和endPage方法即可,中间代码
的调用结果已经存在于Page的result中,如果你在一个返回一个结果的地方调用PageHelper,返回的结果仍然是一个List,取第一个值即
可(我想没人会在这种地方这么用,当然这样也不出错)。
另外在startPage和endPage中间的所有mybatis代码都会被分页,而且PageHelper只会保留最后一次的结果,因而使用时需要保证每次只在其中执行一个mybatis查询,如果有多个分页,请多次使用startPage和endPage。
[转]Mybatis极其(最)简(好)单(用)的一个分页插件
原文:http://www.cnblogs.com/dirgo/p/5189656.html