mybatis框架下物理分頁的實現(整個工程採用的是springmvc、spring、mybatis框架,數據庫是mysql數據庫)

(一)關於分頁攔截器的簡單理解

    首先,要開發MyBatis的插件須要實現org.apache.ibatis.plugin.Interceptor接口,這個接口將會要求實現幾個方法:intercept()、plugin()及setProperties(),intercept方法是開發人員所要執行的操做,plugin是將你插件放入到MyBatis的插件集合中去,而setProperties這是在你配置你插件的時候將plugins/plugin/properties的值設置到該插件中。
    該方法的第一句話就是得到Intercepts註解,接下來將得到在Intercepts裏面的參數@Signature註解內容,在該註解中包含三個參數,分別是type,method,args。Type指定要攔截的類對象,method是指明要攔截該類的哪一個方法,第三個是指明要攔截的方法參數集合。在Intercepts中能夠配置多個@Signature。那麼便對這寫值進行遍歷,已得到對應的type、method以及args。最終是得到一個HashMap對象,這些對象裏面的鍵是類對象,而值是指定的類中方法對象。執行該端程序以後,更具target的classLoader和接口,來建立一個代理,而且,InvocationHandler是建立一個新的Plugin對象,同時將target,interceptor以及signatureMap傳遞給Plugin對象,固然,這裏的Plugin也實現了Invocation接口。那麼target對象全部的方法調用都會觸發Plugin中的invoke方法,那麼這裏將執行開發者全部插入的操做。html

    另外對攔截器類裏面幾個關鍵的類作出解釋:java

(1)BoundSql類 ,封裝mybatis最終產生sql的類,包括sql語句,參數,參數源數據等。
(2)MappedStatement類,MappedStatement類在Mybatis框架中用於表示XML文件中一個sql語句節點,即一個<select />、<update />或者<insert />標籤。Mybatis框架在初始化階段會對XML配置文件進行讀取,將其中的sql語句節點對象化爲一個個MappedStatement對象。spring

   總結,本攔截器實現的目標就是在進行數據庫查詢操做以前,從配置文件讀出相應的sql語句,將相應的參數拼接到其中,而後再進行查詢。固然在拼接sql語句以前,先查詢了一下數據庫中相應記錄的總數sql

(二)攔截器類PageIntercepter.java:

 

[java]  view plain  copy
 
  1. package cn.zyy.paging.intercepter;  
  2.   
  3. import java.sql.Connection;  
  4. import java.sql.PreparedStatement;  
  5. import java.sql.ResultSet;  
  6. import java.sql.SQLException;  
  7. import java.util.List;  
  8. import java.util.Properties;  
  9.   
  10. import org.apache.ibatis.mapping.BoundSql;  
  11. import org.apache.ibatis.mapping.MappedStatement;  
  12. import org.apache.ibatis.mapping.ParameterMapping;  
  13. import org.apache.ibatis.mapping.ParameterMode;  
  14. import org.apache.ibatis.mapping.SqlSource;  
  15. import org.apache.ibatis.plugin.Interceptor;  
  16. import org.apache.ibatis.plugin.Intercepts;  
  17. import org.apache.ibatis.plugin.Invocation;  
  18. import org.apache.ibatis.plugin.Plugin;  
  19. import org.apache.ibatis.reflection.MetaObject;  
  20. import org.apache.ibatis.session.Configuration;  
  21. import org.apache.ibatis.session.RowBounds;  
  22. import org.apache.ibatis.type.TypeHandler;  
  23. import org.apache.ibatis.type.TypeHandlerRegistry;   
  24. import cn.zyy.paging.vo.PageObject;  
  25. @Intercepts({@org.apache.ibatis.plugin.Signature(method="query", type=org.apache.ibatis.executor.Executor.class, args={MappedStatement.class, Object.class, RowBounds.class, org.apache.ibatis.session.ResultHandler.class})})  
  26. public class PageIntercepter implements Interceptor{  
  27.     @Override  
  28.     public Object intercept(Invocation invocation) throws Throwable {  
  29.         MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];  
  30.         Object object = invocation.getArgs()[1];  
  31.         if(object instanceof PageObject){  
  32.               
  33.             PageObject pageObject = (PageObject) object;  
  34.             BoundSql boundSql = mappedStatement.getBoundSql(object);  
  35.             String sql = boundSql.getSql();  
  36.               
  37.             int count = getCount(mappedStatement,boundSql);  
  38.             pageObject.setCount(count);  
  39.             int pages = (pageObject.getCount()+pageObject.getNumber()-1)/pageObject.getNumber();  
  40.             pageObject.setPages(pages>0?pages:1);  
  41.               
  42.             int offset = (pageObject.getPage() - 1) * pageObject.getNumber();  
  43.             int limit = pageObject.getNumber();  
  44.             String pageSql = pageSql(sql, offset, limit);  
  45.             BoundSql pageBoundSql = new BoundSql(mappedStatement.getConfiguration(), pageSql, boundSql.getParameterMappings(), boundSql.getParameterObject());  
  46.             MappedStatement pageMappedStatement = pageMappedStatement(mappedStatement, new PageSqlSource(pageBoundSql));  
  47.             invocation.getArgs()[0] = pageMappedStatement;  
  48.             invocation.getArgs()[2] = RowBounds.DEFAULT;  
  49.         }  
  50.         return invocation.proceed();  
  51.     }  
  52.   
  53.     @Override  
  54.     public Object plugin(Object object) {  
  55.         // TODO Auto-generated method stub  
  56.         return Plugin.wrap(object, this);  
  57.     }  
  58.   
  59.     @Override  
  60.     public void setProperties(Properties properties) {  
  61.         // TODO Auto-generated method stub  
  62.           
  63.     }  
  64.   
  65.     private int getCount(MappedStatement mappedStatement, BoundSql boundSql) throws SQLException {  
  66.           
  67.         Connection connection = null;  
  68.         PreparedStatement ps = null;  
  69.         ResultSet rs = null;  
  70.           
  71.         try {  
  72.             String countSql = countSql(boundSql.getSql());  
  73.             connection = mappedStatement.getConfiguration().getEnvironment().getDataSource().getConnection();  
  74.             ps = connection.prepareStatement(countSql);  
  75.             BoundSql countBoundSql = new BoundSql(mappedStatement.getConfiguration(), countSql, boundSql.getParameterMappings(), boundSql.getParameterObject());  
  76.             setCountParameters(ps, mappedStatement, countBoundSql);  
  77.             rs = ps.executeQuery();  
  78.             int count = 0;  
  79.              if (rs.next())  
  80.               {  
  81.                 count = rs.getInt(1);  
  82.               }  
  83.             return count;  
  84.         } catch (Exception e) {  
  85.             return 1000;  
  86.         }finally{  
  87.              try {  
  88.                 rs.close();  
  89.               } catch (Exception localException4) {  
  90.               }  
  91.               try {  
  92.                 ps.close();  
  93.               } catch (Exception localException5) {  
  94.               }  
  95.               try {  
  96.                 connection.close();  
  97.               }  
  98.               catch (Exception localException6) {  
  99.               }  
  100.         }  
  101.     }  
  102.       
  103.     private static String countSql(String sql){  
  104.         sql = sql.toUpperCase();  
  105.         StringBuffer countSql = new StringBuffer();  
  106.         countSql.append("SELECT COUNT(1) FROM (");  
  107.         countSql.append(sql.substring(0, sql.indexOf("ORDER BY")==-1?sql.length():sql.indexOf("ORDER BY")-1));  
  108.         countSql.append(") PAY_PAGE_T");  
  109.         return countSql.toString();  
  110.     }  
  111.       
  112.     private static void setCountParameters(PreparedStatement ps, MappedStatement mappedStatement, BoundSql boundSql) throws SQLException {  
  113.         List<ParameterMapping> parameterMappingList = boundSql.getParameterMappings();  
  114.         if (parameterMappingList != null)  
  115.         {  
  116.           Configuration configuration = mappedStatement.getConfiguration();  
  117.           TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();  
  118.           Object parameterObject = boundSql.getParameterObject();  
  119.           MetaObject metaObject = parameterObject == null ? null : configuration.newMetaObject(parameterObject);  
  120.   
  121.           int n = 1;  
  122.           for (ParameterMapping parameterMapping : parameterMappingList)  
  123.           {  
  124.             if ((parameterMapping.getMode() == ParameterMode.IN) || (parameterMapping.getMode() == ParameterMode.INOUT))  
  125.             {  
  126.               String property = parameterMapping.getProperty();  
  127.               Object value = null;  
  128.               if (parameterObject != null)  
  129.               {  
  130.                 if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass()))  
  131.                 {  
  132.                   value = parameterObject;  
  133.                 }  
  134.                 else  
  135.                 {  
  136.                   value = metaObject == null ? null : metaObject.getValue(property);  
  137.                 }  
  138.               }  
  139.   
  140.               TypeHandler typeHandler = parameterMapping.getTypeHandler();  
  141.               typeHandler.setParameter(ps, n, value, parameterMapping.getJdbcType());  
  142.             }  
  143.   
  144.             n++;  
  145.           }  
  146.         }  
  147.     }  
  148.       
  149.     private String pageSql(String sql, int offset, int limit) {  
  150.         sql = sql.toUpperCase();  
  151.         StringBuffer pageSql = new StringBuffer();  
  152.         pageSql.append(sql);  
  153.         pageSql.append(" LIMIT ");  
  154.         pageSql.append(offset);  
  155.         pageSql.append(", ");  
  156.         pageSql.append(limit);  
  157.         return pageSql.toString();  
  158.       }  
  159.       
  160.     private MappedStatement pageMappedStatement(MappedStatement mappedStatement, SqlSource sqlSource)  
  161.       {  
  162.         MappedStatement.Builder builder = new MappedStatement.Builder(  
  163.           mappedStatement.getConfiguration(),   
  164.           mappedStatement.getId(),   
  165.           sqlSource,   
  166.           mappedStatement.getSqlCommandType());  
  167.   
  168.         builder.resource(mappedStatement.getResource());  
  169.         builder.fetchSize(mappedStatement.getFetchSize());  
  170.         builder.statementType(mappedStatement.getStatementType());  
  171.         builder.keyGenerator(mappedStatement.getKeyGenerator());  
  172.         builder.timeout(mappedStatement.getTimeout());  
  173.         builder.parameterMap(mappedStatement.getParameterMap());  
  174.         builder.resultMaps(mappedStatement.getResultMaps());  
  175.         builder.cache(mappedStatement.getCache());  
  176.         builder.resultSetType(mappedStatement.getResultSetType());  
  177.         builder.flushCacheRequired(mappedStatement.isFlushCacheRequired());  
  178.         builder.useCache(mappedStatement.isUseCache());  
  179.         builder.resultOrdered(mappedStatement.isResultOrdered());  
  180.         builder.databaseId(mappedStatement.getDatabaseId());  
  181.         builder.lang(mappedStatement.getLang());  
  182.         if (mappedStatement.getKeyProperties() != null)  
  183.         {  
  184.           for (String keyProperty : mappedStatement.getKeyProperties())  
  185.           {  
  186.             builder.keyProperty(keyProperty);  
  187.           }  
  188.         }  
  189.         if (mappedStatement.getKeyColumns() != null)  
  190.         {  
  191.           for (String keyColumn : mappedStatement.getKeyColumns())  
  192.           {  
  193.             builder.keyColumn(keyColumn);  
  194.           }  
  195.         }  
  196.   
  197.         return builder.build();  
  198.       }  
  199.       
  200.      public static class PageSqlSource implements SqlSource {  
  201.         private BoundSql boundSql;  
  202.   
  203.         public PageSqlSource(BoundSql boundSql) {  
  204.           this.boundSql = boundSql;  
  205.         }  
  206.   
  207.         public BoundSql getBoundSql(Object parameterObject)  
  208.         {  
  209.           return this.boundSql;  
  210.         }  
  211.       }  
  212.   
  213. }  

 

(三)spring配置文件和mybatis配置文件

mybatis配置文件中主要是配置相關的vo類和攔截器數據庫

 [html] view plain copyexpress

 

spring的配置文件中主要就是實現mybatis和spring框架的整合apache

  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"  
  4.     xmlns:tx="http://www.springframework.org/schema/tx" xmlns:mvc="http://www.springframework.org/schema/mvc"  
  5.     xmlns:aop="http://www.springframework.org/schema/aop"  
  6.     xsi:schemaLocation="  
  7.         http://www.springframework.org/schema/aop   
  8.         http://www.springframework.org/schema/aop/spring-aop-3.2.xsd  
  9.         http://www.springframework.org/schema/mvc   
  10.         http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd  
  11.         http://www.springframework.org/schema/beans   
  12.         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
  13.         http://www.springframework.org/schema/tx   
  14.         http://www.springframework.org/schema/tx/spring-tx-3.0.xsd  
  15.         http://www.springframework.org/schema/context   
  16.         http://www.springframework.org/schema/context/spring-context-2.5.xsd">  
  17.           
  18.         <!-- 讀取屬性文件 -->  
  19.         <bean class = "org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">  
  20.             <property name = "location" value = "classpath:db.properties"></property>  
  21.         </bean>  
  22.         <!-- 配置數據源 -->  
  23.         <bean id = "dataSource" class = "org.springframework.jdbc.datasource.DriverManagerDataSource">  
  24.             <property name = "driverClassName" value = "${driverClass}"></property>  
  25.             <property name = "url" value = "${url}"></property>  
  26.             <property name = "username" value = "${username}"></property>  
  27.             <property name = "password" value = "${password}"></property>  
  28.         </bean>  
  29.         <!-- 配置 sqlSessionFactory,實現spring和mybatis框架的整合-->  
  30.         <bean id = "sqlSessionFactory" class = "org.mybatis.spring.SqlSessionFactoryBean">  
  31.             <property name = "dataSource" ref = "dataSource"></property>  
  32.             <property name = "configLocation" value = "classpath:mybatis-config.xml"></property>  
  33.             <property name = "mapperLocations" value = "classpath:cn/zyy/paging/xml/*.xml"></property>  
  34.             <property name = "typeAliasesPackage" value = "cn.zyy.paging.vo"></property>  
  35.         </bean>  
  36.         <!-- 配置 MapperScannerConfigurer:將Mapper接口生成代理注入到Spring -->  
  37.         <bean class = "org.mybatis.spring.mapper.MapperScannerConfigurer">  
  38.             <property name = "sqlSessionFactoryBeanName" value = "sqlSessionFactory"></property>  
  39.             <property name = "basePackage" value = "cn.zyy.paging.dao"></property>  
  40.         </bean>  
  41.           
  42.         <!-- 配置事務管理器 -->  
  43.         <bean id = "txManage" class = "org.springframework.jdbc.datasource.DataSourceTransactionManager">  
  44.             <property name = "dataSource" ref = "dataSource"></property>  
  45.         </bean>  
  46.           
  47.         <!-- 配置事務傳播機制 -->  
  48.         <tx:advice id = "txAdvice" transaction-manager="txManage">  
  49.             <tx:attributes>  
  50.                 <tx:method name="*" propagation="REQUIRED"/>  
  51.             </tx:attributes>  
  52.         </tx:advice>  
  53.         <!-- 利用aop實現動態代理 -->  
  54.         <aop:config>  
  55.             <aop:pointcut expression="execution(* cn.zyy.paging.service.*.*(..))" id="pointcut"/>  
  56.             <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"/>  
  57.         </aop:config>  
  58.         <!-- 掃描springmvc不能掃描的service類 -->  
  59.         <context:component-scan base-package="cn.zyy.paging.service"></context:component-scan>  
  60. </beans>  
相關文章
相關標籤/搜索