mybatis分页案例

我是参考公司框架,以及网上资料整理的,希望大家能细化或者指点。

package com.botech.skynet.common;

import java.sql.Connection;
import java.util.Map;
import java.util.Properties;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ibatis.executor.statement.StatementHandler;
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.scripting.defaults.DefaultParameterHandler;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.RowBounds;
import org.springframework.util.StringUtils;

//import com.botech.skynet.comm.qvo.DataGridQO;

@Intercepts({@Signature(type =StatementHandler.class, method = "prepare", args ={Connection.class})})  
public class PaginationInterceptor implements Interceptor {
	
	Log log= LogFactory.getLog(LogFactory.class);
	@Override
	public Object intercept(Invocation invocation) throws Throwable {
          StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
          
		//MetaObject是Mybatis提供的一个的工具类,通过它包装一个对象后可以获取或设置该对象的原本不可访问的属性(比如那些私有属性)。
	    MetaObject metaStatementHandler = MetaObject.forObject(statementHandler,SystemMetaObject.DEFAULT_OBJECT_FACTORY,
				SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY);
	     
	    //判断是否使用分页,如果不判断,那么所有的sql将会给予分页
			RowBounds rowBounds = (RowBounds) metaStatementHandler.getValue("delegate.rowBounds");
			if (rowBounds == null || rowBounds == RowBounds.DEFAULT) {
				return invocation.proceed();
			}
		  //获取原始sql
		  String originalSql = (String) metaStatementHandler.getValue("delegate.boundSql.sql");
		  //获取mybatis配置参数
			Configuration configuration = (Configuration) metaStatementHandler
					.getValue("delegate.configuration");
		String dialect=	(String) configuration.getVariables().get("dialect");
		//获取参数d
		DefaultParameterHandler defaultParameterHandler = (DefaultParameterHandler) metaStatementHandler
				.getValue("delegate.parameterHandler");
		
		PageObject dtQo = null;
		Object sidx = null;
		Object sord = null;
		
		if(defaultParameterHandler.getParameterObject() instanceof PageObject){
			dtQo = (PageObject) defaultParameterHandler.getParameterObject();
			sidx = dtQo.getSort();
			sord = dtQo.getOrder();
		}else{
			Map parameterMap = (Map) defaultParameterHandler.getParameterObject();
			sidx = parameterMap.get("_sidx");
			sord = parameterMap.get("_sord");
		}
		
		OracleDialect oracle = new OracleDialect();
		if(dialect.equalsIgnoreCase("oracle") ){
			metaStatementHandler.setValue("delegate.boundSql.sql", oracle
					.getLimitString(originalSql, rowBounds.getOffset(), rowBounds
							.getLimit()));	
			  log.info("分页成功--------------------------------->");
		}else{
			return invocation.proceed();
		} 
		 metaStatementHandler.setValue("delegate.rowBounds.offset", RowBounds.NO_ROW_OFFSET);
         metaStatementHandler.setValue("delegate.rowBounds.limit", RowBounds.NO_ROW_LIMIT);
        return invocation.proceed();
	}

	@Override
	public Object plugin(Object target) {
		  // 当目标类是StatementHandler类型时,才包装目标类,否者直接返回目标本身,减少目标被代理的 
		 if (target instanceof StatementHandler) {  
		        return Plugin.wrap(target, this);  
		    } else {  
		        return target;  
		    }  
	}

	@Override
	public void setProperties(Properties target) {
		// TODO Auto-generated method stub

	}

}

 配置文件spring

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" 
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
    xmlns:util="http://www.springframework.org/schema/util"                              
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
        http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.0.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd"
        default-lazy-init="true">
        
        <description>spring配置</description>
        
        <!-- 加载数据库文件 -->
      <bean id="propertyConfigurer"    class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="classpath:config.properties" />
    </bean>

       <!-- 配置数据库dbcp池链接 -->
       <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" 
          destroy-method="close">  
            <property name="driverClassName" value="${driver}" />  
            <property name="url" value="${url}" />  
            <property name="username" value="${username}" />  
            <property name="password" value="${password}" />  
            <!-- 初始化连接大小 -->  
            <property name="initialSize" value="${initialSize}"></property>  
            <!-- 连接池最大数量 -->  
            <property name="maxActive" value="${maxActive}"></property>  
            <!-- 连接池最大空闲 -->  
            <property name="maxIdle" value="${maxIdle}"></property>  
            <!-- 连接池最小空闲 -->  
            <property name="minIdle" value="${minIdle}"></property>  
            <!-- 获取连接最大等待时间 -->  
            <property name="maxWait" value="${maxWait}"></property>  
       </bean>
       <bean id="txManager"  class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
                <property name="dataSource" ref="dataSource"></property>
       </bean>
        <tx:advice id ="txAdvice"  transaction-manager="txManager">
                <tx:attributes>
                    <tx:method name="get*" read-only="true"/>
                    <tx:method name="select*" read-only="true"/>
                    <tx:method name="queryFor*" read-only="true"/>
                    <tx:method name="*"/>
                </tx:attributes>
        </tx:advice>
        
       <!-- 拦截器分页mybatis -->
       <bean id="paginationInterceptor" class="com.botech.skynet.common.PaginationInterceptor"/>
        
        <bean id="sqlSessionFactory"  class="org.mybatis.spring.SqlSessionFactoryBean" >
          <property name="dataSource" ref="dataSource"></property>
           <!-- 自动扫描mapping.xml文件 删除正常           -->
           <property name="mapperLocations" value="classpath:com/botech/skynet/base/persistence/*.xml" />
           <property name="plugins">
                   <array>
                            <ref bean="paginationInterceptor"/>
                   </array>
           </property>
           <property name="configurationProperties">
                   <props>
                          <prop key="dialect">oracle</prop>
                   </props>
           </property>
           
        </bean>
          <!-- 配置sqlSessionTemplate  --> 
        <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
            <constructor-arg index="0" ref="sqlSessionFactory" />
        </bean>
     
        <!-- 配置mybatis的sqlMap及接口的映射 -->
        <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
            <property name="basePackage" value="com.botech.skynet.base.persistence"/>
            <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>  
        </bean>
    
         <!-- 扫描控件,不包括controller -->
        <context:component-scan base-package="com.botech">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
      </context:component-scan>
    
</beans>

dao的实现

package com.botech.skynet.base.persistence.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import org.springframework.stereotype.Repository;

import com.botech.skynet.base.persistence.IUserDao;
import com.botech.skynet.base.persistence.UserTestDao;
import com.botech.skynet.common.BaseDaoImpl;
import com.botech.ywzx.index.vo.User;
import com.botech.ywzx.index.vo.UserQO;

@Repository
public class UserTestDaoImpl extends BaseDaoImpl implements UserTestDao{

    @Override
    public UserQO selectByPrimaryKey(int userId) {
        Map map = new HashMap();
        map.put("id", userId);
        this.getPage();
        return (UserQO) queryForObject("com.botech.skynet.base.persistence.UserTestDao.selectByPrimaryKey",map);
    }

    @Override
    public ArrayList<UserQO> getPage() {
        Map map = new HashMap();
        map.put("id", 999);
        return (ArrayList<UserQO>) queryForListPagination(UserTestDao.class.getName()+".selectByPrimaryKey", map, 1, 10);
    }

}

basedaoimpl分页代码部分
实现spring的session管理,同时将的sqlsessiontemplate注入到spring中,有spring统一管理,我们无需管理session

@Component
public class BaseDaoImpl extends SqlSessionDaoSupport implements BaseDao {
    
     @Autowired
     public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate)
        {
         super.setSqlSessionTemplate(sqlSessionTemplate);
        }

/**
         * MyBatis物理分页方法
         * @param sqlKey: SQL ID
         * @param map: 查询参数Map对象 
         * @param page: 当前页数
         * @param rows: 每页记录数
         * @return List
         */
        public List queryForListPagination(String sqlKey, Map map, int page, int rows) {
            return this.getSqlSession().selectList(sqlKey, putFixAuthDataParam(map), new RowBounds((page-1)*rows+1, rows));
        }
        


}

 

1、具体的一些扫描注解,我就不说了,因为这个mybatis的分页,其实主要是一种原理的理解,采用这种方式实现,就类似于拦截器将代理sql拦截,然后处理。

2、采用basedao的方式,是为了让spring更好的管理session,我们直接使用即可,如果你想自己扩展,可以参考public interface SqlSession extends Closeable 中 方法重写

3、在源码中  的解释  

   /**
   * Users should use this method to get a SqlSession to call its statement methods
   * This is SqlSession is managed by spring. Users should not commit/rollback/close it
   * because it will be automatically done.
   *
   * @return Spring managed thread safe SqlSession
   */
  public SqlSession getSqlSession() {
    return this.sqlSession;
  } 

4、将spring中的bean注入,实现mybatis与spring的session管理 

  @Autowired
  public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate)
     {
      super.setSqlSessionTemplate(sqlSessionTemplate);
     }

 

posted @ 2015-12-29 17:22  笑怪兽  阅读(2885)  评论(0编辑  收藏  举报