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方法,那么这里将执行开发者所有插入的操作。

    另外对拦截器类里面几个关键的类做出解释:

(1)BoundSql类 ,封装mybatis最终产生sql的类,包括sql语句,参数,参数源数据等。
(2)MappedStatement类,MappedStatement类在Mybatis框架中用于表示XML文件中一个sql语句节点,即一个<select />、<update />或者<insert />标签。Mybatis框架在初始化阶段会对XML配置文件进行读取,将其中的sql语句节点对象化为一个个MappedStatement对象。

   总结,本拦截器实现的目标就是在进行数据库查询操作之前,从配置文件读出相应的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 copy

 

spring的配置文件中主要就是实现mybatis和spring框架的整合

  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>  
posted @ 2017-12-12 10:27  start枫  阅读(340)  评论(0编辑  收藏  举报