Mybatis实现物理分页

Mybatis的自带分页方法只是逻辑分页,如果数据量很大,内存会溢出,不知道为什么开源组织不在里面实现类似Hibernate的物理分页处理方法。在不改动Mybatis源代码的情况下,怎么使Mybatis支持物理分页呢?下面我们来看看。

 

(1)新建一个Java类Dialect.java,该类的内容如下:

Java代码  
  1. package org.mybatis.extend.interceptor;  

  2.   

  3. public  abstract  class Dialect {  

  4.   

  5.     public  static  enum Type{  

  6.         MYSQL,  

  7.         ORACLE  

  8.     }  

  9.       

  10.     public  abstract String getLimitString(String sqlint skipResults, int maxResults);  

  11.       

  12. }  

 

 

(2)新建一个Java类OracleDialect.java,该类继承Dialect 类,具体的内容如下:

Java代码  
  1. package org.mybatis.extend.interceptor;  

  2.   

  3. public  class OracleDialect  extends Dialect{  

  4.   

  5.     /* (non-Javadoc)  

  6.      * @see org.mybatis.extend.interceptor.IDialect#getLimitString(java.lang.String, int, int) 

  7.      */  

  8.     @Override  

  9.     public String getLimitString(String sqlint offset,  int limit) {  

  10.   

  11.         sql = sql.trim();  

  12.         StringBuffer pagingSelect = new StringBuffer(sql.length() +  100 );  

  13.           

  14.         pagingSelect.append("select * from ( select row_.*, rownum rownum_ from ( ");  

  15.           

  16.         pagingSelect.append(sql);  

  17.           

  18.         pagingSelect.append(" ) row_ ) where rownum_ > ").append(offset).append(" and rownum_ <= ").append(offset + limit);  

  19.           

  20.         return pagingSelect.toString();  

  21.     }  

  22.   

  23. }  

 

(3)新建一个Mybaits的拦截器PaginationInterceptor.java,实现Interceptor接口,该类的内容如下:

Java代码 

package org.mybatis.extend.interceptor

import java.sql.Connection;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.apache.ibatis.executor.parameter.DefaultParameterHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
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.session.Configuration;
import org.apache.ibatis.session.RowBounds;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import platform.pages.mybatis.dialects.MysqlDialect;
import platform.pages.mybatis.dialects.OracleDialect;

/**
 * Mybaits的拦截器
 * 
 * @author fhx 2013-1-27 下午03:04:33
 */
@Intercepts( { @Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class }) })
public class PaginationInterceptor implements Interceptor {

 protected static Logger log = LoggerFactory.getLogger(PaginationInterceptor.class);

 @Override
 public Object intercept(Invocation invocation) throws Throwable {
  StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
  BoundSql boundSql2 = statementHandler.getBoundSql();
  List list = boundSql2.getParameterMappings();
  MetaObject metaStatementHandler = MetaObject.forObject(statementHandler);
  RowBounds rowBounds = (RowBounds) boundSql2.getParameterObject();
  if (rowBounds == null || rowBounds == RowBounds.DEFAULT) {
   return invocation.proceed();
  }
  String originalSql = (String) metaStatementHandler.getValue("delegate.boundSql.sql");
  Configuration configuration = (Configuration) metaStatementHandler.getValue("delegate.configuration");
  Dialect.Type databaseType = null;
  try {
   databaseType = Dialect.Type.valueOf(configuration.getVariables().getProperty("dialect").toUpperCase());
  } catch (Exception e) {
   System.out.println("mybatis-config.xml中未设置数据库类型");
  }
  if (databaseType == null) {
   throw new RuntimeException(
     "the value of the dialect property in configuration.xml is not defined : " + configuration.getVariables().getProperty("dialect"));
  }
  Dialect dialect = null;
  switch (databaseType) {
  case ORACLE: // oracle 分页
   dialect = new OracleDialect();
   break;
  case MYSQL: // MySQL分页
   dialect = new MysqlDialect();
   break;
  }
  metaStatementHandler.setValue("delegate.boundSql.sql", dialect.getLimitString(originalSql, rowBounds.getOffset(), rowBounds.getLimit()));

  metaStatementHandler.setValue("delegate.rowBounds.offset",RowBounds.NO_ROW_OFFSET);

  metaStatementHandler.setValue("delegate.rowBounds.limit",RowBounds.NO_ROW_LIMIT);

  if (log.isDebugEnabled()) {
   BoundSql boundSql = statementHandler.getBoundSql();
   log.debug(" 生成分页SQL : " + boundSql.getSql());
  }
  return invocation.proceed();
 }

 @Override
 public Object plugin(Object target) {
  return Plugin.wrap(target, this);
 }

 @Override
 public void setProperties(Properties arg0) {

 }

}

 

 (4)将Mybatis的拦截器配置到Mybatis的全局配置文件(mybatis.cfg.xml)中,具体如下:

Java代码 
  1. <?xml version="1.0" encoding= "UTF-8" ?>  

  2.   

  3. <!DOCTYPE configuration PUBLIC   

  4.     "-//mybatis.org//DTD Config 3.0//EN"  

  5.     "http://mybatis.org/dtd/mybatis-3-config.dtd">  

  6.   

  7. <configuration>  

  8.     <properties>  

  9.               <property name="dialect" value= "oracle"/>  

  10.     </properties>  

  11.           

  12.     <plugins>  

  13.             <plugin interceptor="org.mybatis.extend.interceptor.PaginationInterceptor"/>  

  14.     </plugins>  

  15.          

  16. </configuration>  

 

(5)使用方法同Mybatis逻辑分页一样,拦截器会自动拦截执行SQL的地方,加上分页代码:

Java代码 
  1. getSqlSession().selectList(sqlId, paramMap,new RowBounds(pageId, pageSize));  

              (6) 和spring集成封装有superDao

public class SupperDao extends SqlSessionDaoSupport{
 
 protected Logger log = LoggerFactory.getLogger(getClass());
 
 /**
  * 保存
  * @param key
  * @param object
  */
 public void save(String key, Object object) {
  getSqlSession().insert(key, object);
 }
 
 /**
  * 删除
  * @param key
  * @param id
  */
 public void delete(String key, Serializable id) {
  getSqlSession().delete(key, id);
 }
 
 /**
  * 删除
  * @param key
  * @param object
  */
 public void delete(String key, Object object) {
  getSqlSession().delete(key, object);
 }
 
 /**
  * 查询 返回一个结果
  * @param <T>
  * @param key
  * @param params
  * @return
  */
 public <T> T get(String key, Object params) {
  return (T) getSqlSession().selectOne(key, params);
 }
 
 /**
  * 查询 返回多个结果
  * @param <T>
  * @param key
  * @return
  */
 public <T> List<T> findList(String key) {
  return getSqlSession().selectList(key);
 }
 
 /**
  * 分页查询
  * @param <T>
  * @param key
  * @param offset
  * @param pageSize
  * @return
  */
 public <T> List<T> findList(String key,int offset,int pageSize) {
  return getSqlSession().selectList(key,new RowBounds(offset, pageSize));
 }
 
 /**
  * 查询 可带参数 返回多个结果
  * @param <T>
  * @param key
  * @param params
  * @return
  */
 public <T> List<T> findList(String key, Object params) {
  return getSqlSession().selectList(key, params);
 }
 
 /**
  * 分页查询 可带参数
  * @param <T>
  * @param key
  * @param params
  * @param pageNo
  * @param pageSize
  * @return
  */
 public <T> List<T> findList(String key, Object params,int pageOffset,int pageSize) {
  return getSqlSession().selectList(key, params,new RowBounds(pageOffset, pageSize));
 }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值