badqiu

          XPer
          隨筆 - 46, 文章 - 3, 評論 - 195, 引用 - 0
          數據加載中……

          ibatis3基于方言的分頁

          (注:以下代碼是基于ibatis3 beta4的擴展,ibatis3正式版如果實現改變,將會繼續跟進修改)

           

           

          iBatis3默認使用的分頁是基于游標的分頁,而這種分頁在不同的數據庫上性能差異不一致,最好的辦法當然是使用類似hibernate的基于方言(Dialect)的物理分頁功能。

          iBatis3現在提供插件功能,通過插件我們可以編寫自己的攔截器來攔截iBatis3的主要執行方法來完成相關功能的擴展。

           

           

           

          能夠攔截的的類如下:

           

          Java代碼 
          1. Executor  
          2.     (update,query,flushStatements,commit,rollback,getTransaction,close,isClosed)  
          3. ParameterHandler  
          4.     (getParameterObject,setParameters)  
          5. ResultSetHandler  
          6.     (handleResultSets,handleOutputParameters)  
          7. StatementHandler  
          8.     (prepare,parameterize,batch,update,query)  

           

           但此次我們感興趣的是Executor.query()方法,查詢方法最終都是執行該方法。

          該方法完整是:

           

          Java代碼 
          1. Executor.query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException;  

           

           

          分頁方言的基本實現:

          以Mysql數據庫示例,即有一個方法 query(sql,offset,limit);

           

           

          Java代碼 
          1. query("select * from user",5,10);  
           

           

          經過我們的攔截器攔截處理,變成

           

          Java代碼 
          1. query("select * from user limit 5,10",0,0);  
           

           

          1.攔截類實現:

           

          Java代碼 
          1. @Intercepts({@Signature(  
          2.         type= Executor.class,  
          3.         method = "query",  
          4.         args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})})  
          5. public class OffsetLimitInterceptor implements Interceptor{  
          6.     static int MAPPED_STATEMENT_INDEX = 0;  
          7.     static int PARAMETER_INDEX = 1;  
          8.     static int ROWBOUNDS_INDEX = 2;  
          9.     static int RESULT_HANDLER_INDEX = 3;  
          10.       
          11.     Dialect dialect;  
          12.       
          13.     public Object intercept(Invocation invocation) throws Throwable {  
          14.         processIntercept(invocation.getArgs());  
          15.         return invocation.proceed();  
          16.     }  
          17.   
          18.     void processIntercept(final Object[] queryArgs) {  
          19.         //queryArgs = query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler)  
          20.         MappedStatement ms = (MappedStatement)queryArgs[MAPPED_STATEMENT_INDEX];  
          21.         Object parameter = queryArgs[PARAMETER_INDEX];  
          22.         final RowBounds rowBounds = (RowBounds)queryArgs[ROWBOUNDS_INDEX];  
          23.         int offset = rowBounds.getOffset();  
          24.         int limit = rowBounds.getLimit();  
          25.           
          26.         if(dialect.supportsLimit() && (offset != RowBounds.NO_ROW_OFFSET || limit != RowBounds.NO_ROW_LIMIT)) {  
          27.             BoundSql boundSql = ms.getBoundSql(parameter);  
          28.             String sql = boundSql.getSql().trim();  
          29.             if (dialect.supportsLimitOffset()) {  
          30.                 sql = dialect.getLimitString(sql, offset, limit);  
          31.                 offset = RowBounds.NO_ROW_OFFSET;  
          32.             } else {  
          33.                 sql = dialect.getLimitString(sql, 0, limit);  
          34.             }  
          35.             limit = RowBounds.NO_ROW_LIMIT;  
          36.               
          37.             queryArgs[ROWBOUNDS_INDEX] = new RowBounds(offset,limit);  
          38.             BoundSql newBoundSql = new BoundSql(sql, boundSql.getParameterMappings(), boundSql.getParameterObject());  
          39.             MappedStatement newMs = copyFromMappedStatement(ms, new BoundSqlSqlSource(newBoundSql));  
          40.             queryArgs[MAPPED_STATEMENT_INDEX] = newMs;  
          41.         }  
          42.     }  
          43.       
          44.     private MappedStatement copyFromMappedStatement(MappedStatement ms,SqlSource newSqlSource) {  
          45.         Builder builder = new MappedStatement.Builder(ms.getConfiguration(),ms.getId(),newSqlSource,ms.getSqlCommandType());  
          46.         builder.resource(ms.getResource());  
          47.         builder.fetchSize(ms.getFetchSize());  
          48.         builder.statementType(ms.getStatementType());  
          49.         builder.keyGenerator(ms.getKeyGenerator());  
          50.         builder.keyProperty(ms.getKeyProperty());  
          51.         builder.timeout(ms.getTimeout());  
          52.         builder.parameterMap(ms.getParameterMap());  
          53.         builder.resultMaps(ms.getResultMaps());  
          54.         builder.cache(ms.getCache());  
          55.         MappedStatement newMs = builder.build();  
          56.         return newMs;  
          57.     }  
          58.   
          59.     public Object plugin(Object target) {  
          60.         return Plugin.wrap(target, this);  
          61.     }  
          62.   
          63.     public void setProperties(Properties properties) {  
          64.         String dialectClass = new PropertiesHelper(properties).getRequiredString("dialectClass");  
          65.         try {  
          66.             dialect = (Dialect)Class.forName(dialectClass).newInstance();  
          67.         } catch (Exception e) {  
          68.             throw new RuntimeException("cannot create dialect instance by dialectClass:"+dialectClass,e);  
          69.         }   
          70.         System.out.println(OffsetLimitInterceptor.class.getSimpleName()+".dialect="+dialectClass);  
          71.     }  
          72.       
          73.     public static class BoundSqlSqlSource implements SqlSource {  
          74.         BoundSql boundSql;  
          75.         public BoundSqlSqlSource(BoundSql boundSql) {  
          76.             this.boundSql = boundSql;  
          77.         }  
          78.         public BoundSql getBoundSql(Object parameterObject) {  
          79.             return boundSql;  
          80.         }  
          81.     }  
          82.       
          83. }  
           

           

          2.ibatis3配置文件內容:

          Xml代碼 
          1. <configuration>  
          2.     <plugins>  
          3.         <!-- 指定數據庫分頁方言Dialect, 其它方言:OracleDialect,SQLServerDialect,SybaseDialect,DB2Dialect,PostgreSQLDialect,MySQLDialect,DerbyDialect-->  
          4.         <plugin interceptor="cn.org.rapid_framework.ibatis3.plugin.OffsetLimitInterceptor">  
          5.             <property name="dialectClass" value="cn.org.rapid_framework.jdbc.dialect.MySQLDialect"/>  
          6.         </plugin>  
          7.     </plugins>  
          8.   
          9.     <environments default="development">  
          10.         <environment id="development">  
          11.             <transactionManager type="JDBC" />  
          12.             <dataSource type="POOLED">  
          13.                 <property name="driver" value="com.mysql.jdbc.Driver" />  
          14.                 <property name="url" value="jdbc:mysql://localhost:3306/test" />  
          15.                 <property name="username" value="root" />  
          16.                 <property name="password" value="123456" />  
          17.             </dataSource>  
          18.         </environment>  
          19.     </environments>  
          20.   
          21.     <mappers>  
          22.         <mapper resource="com/company/project/model/mapper/BlogMapper.xml" />  
          23.     </mappers>  
          24. </configuration>  
           

          3.MysqlDialect實現

          Java代碼 
          1. public class MySQLDialect extends Dialect{  
          2.   
          3.     public boolean supportsLimitOffset(){  
          4.         return true;  
          5.     }  
          6.       
          7.     public boolean supportsLimit() {     
          8.         return true;     
          9.     }    
          10.       
          11.     public String getLimitString(String sql, int offset, int limit) {  
          12.             return getLimitString(sql,offset,String.valueOf(offset),limit,String.valueOf(limit));  
          13.     }  
          14.       
          15.     public String getLimitString(String sql, int offset,String offsetPlaceholder, int limit, String limitPlaceholder) {  
          16.         if (offset > 0) {     
          17.             return sql + " limit "+offsetPlaceholder+","+limitPlaceholder;   
          18.         } else {     
          19.             return sql + " limit "+limitPlaceholder;  
          20.         }    
          21.     }     
          22.     
          23. }  

           

          其它數據庫的Dialect實現請查看:

          http://rapid-framework.googlecode.com/svn/trunk/rapid-framework/src/rapid_framework_common/cn/org/rapid_framework/jdbc/dialect/

           

          4.分頁使用

          直接調用SqlSession.selectList(statement, parameter, new RowBounds(offset,limit))即可使用物理分頁

           

          5.存在的問題

          現不是使用占位符的方式(即不是“limit ?,?”而是使用“limit 8,20”)使用分頁

           

          完整代碼可以查看即將發布的rapid-framework 3.0的ibatis3插件

           

          posted on 2009-10-20 09:04 badqiu 閱讀(3952) 評論(5)  編輯  收藏

          評論

          # re: ibatis3基于方言的分頁  回復  更多評論   

          sqlserver2000怎么辦,oracle怎么辦,db2怎么辦。。。mysql分頁是最簡單的數據庫了。
          2009-11-01 18:10 | spingNo1

          # re: ibatis3基于方言的分頁[未登錄]  回復  更多評論   

          問這個問題前請先仔細再看一下文章內容.
          2009-11-01 19:02 | badqiu

          # re: ibatis3基于方言的分頁  回復  更多評論   

          rapid-framework 3.0的ibatis3插件不錯
          2009-12-17 14:07 | 團派家園

          # re: ibatis3基于方言的分頁  回復  更多評論   

          rapid-framework 好東西啊
          2010-06-04 10:38 | king2ksu

          # re: ibatis3基于方言的分頁  回復  更多評論   

          BoundSql newBoundSql = new BoundSql(sql, boundSql.getParameterMappings(), boundSql.getParameterObject());
          有錯因為BoundSql的構造函數如下,少傳了configuration,應該怎么改呀
          public BoundSql(Configuration configuration, String sql, List parameterMappings, Object parameterObject)

          2011-06-16 17:40 | wypsmall

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 浮梁县| 苗栗县| 芦溪县| 应城市| 西吉县| 香河县| 吴堡县| 高密市| 柏乡县| 和田市| 永春县| 浦城县| 绵竹市| 广丰县| 会昌县| 梅河口市| 惠安县| 康定县| 和林格尔县| 曲松县| 邢台县| 当雄县| 穆棱市| 拉萨市| 大石桥市| 金塔县| 锦州市| 兴山县| 江北区| 台南市| 农安县| 天台县| 长春市| 沙洋县| 华坪县| 梁山县| 四会市| 邵武市| 烟台市| 客服| 盐池县|