我是參考公司框架,以及網上資料整理的,希望大家能細化或者指點。
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);
}
