日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

转:mybatis - 分页功能

發(fā)布時間:2025/4/14 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 转:mybatis - 分页功能 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

本文轉(zhuǎn)自http://www.cnblogs.com/jcli/archive/2011/08/09/2132222.html

mybatis高級應(yīng)用系列一:分頁功能

Mybatis3.0出來已有段時間了,其實自己挺喜歡這樣的一個持久化框架的,因為它簡單實用,學(xué)習(xí)成本低。Mybatis3.0在整體結(jié)構(gòu)上和ibatis2.X差不多,改進特性如下:

1.?????????解析xml引進了Xpath,不像ibatis2.x那樣業(yè)余

2.?????????動態(tài)sqlOGNL解析

3.?????????加入注解配置sql,感覺沒什么特別大的用途,我更喜歡xml方式,代碼和配置分離,這也是ibatis的初衷

4.?????????加強了緩存這塊的功能。Mybatis3.0把緩存模塊分得更細,分為“持久實現(xiàn)(prepetual)”和“資源回收策略實現(xiàn)(eviction)”,更好的對緩存功能進行自己組合和擴展

5.?????????終于加入的plugin功能,就像struts一樣,這樣就可以很好的擴展內(nèi)部的Executor,StatementHandler….等內(nèi)部對象功能。

?

一下只能想到這些了,總之改動后的代碼結(jié)構(gòu)清晰多了,如果各位看下源碼的話,也是學(xué)習(xí)設(shè)計模式很好的課件,里面的代碼用到了很多經(jīng)典的設(shè)計模式,這在之后的系列學(xué)習(xí)中會講到。

?

這一篇文章講下分頁的功能。

?

正如和ibatis以前的版本一樣,mybatis的分頁還是基于內(nèi)存分頁(查找出所有記錄再取出偏移量的記錄,如果jdbc驅(qū)支持absolute定位或者rs.next()到指定偏移位置),其實這樣的分頁實現(xiàn)基本沒用,特別是大量數(shù)據(jù)情況下。

?

要想改變mybatis內(nèi)部的分頁行為,理論上只要把最終要執(zhí)行的sql轉(zhuǎn)變成對應(yīng)的分頁語句就行了。首先,我們熟悉下mybatis內(nèi)部執(zhí)行查詢的動態(tài)交互圖:

?

可以很清楚的看到,真正生成Statement并執(zhí)行sql的語句是StatementHandler接口的某個實現(xiàn),這樣就可以寫個插件對StatementHandler的行為進行攔截。  

package study.mybatis.interceptor;





import java.sql.Connection;

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.mapping.BoundSql;

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.session.Configuration;

import org.apache.ibatis.session.RowBounds;



import study.mybatis.dialect.Dialect;

import study.mybatis.dialect.MySql5Dialect;



@Intercepts({@Signature(type=StatementHandler.class,method="prepare",args={Connection.class})})

publicclass PaginationInterceptor implements Interceptor{



privatefinalstatic Log log = LogFactory.getLog(PaginationInterceptor.class);



@Override

public Object intercept(Invocation invocation) throws Throwable {

StatementHandler statementHandler = (StatementHandler)invocation.getTarget();

BoundSql boundSql = statementHandler.getBoundSql();

MetaObject metaStatementHandler = MetaObject.forObject(statementHandler);

RowBounds rowBounds = (RowBounds)metaStatementHandler.getValue("delegate.rowBounds");

if(rowBounds ==null|| rowBounds == RowBounds.DEFAULT){

return invocation.proceed();

}

Configuration configuration = (Configuration)metaStatementHandler.getValue("delegate.configuration");

Dialect.Type databaseType =null;

try{

databaseType = Dialect.Type.valueOf(configuration.getVariables().getProperty("dialect").toUpperCase());

} catch(Exception e){

//ignore

}

if(databaseType ==null){

thrownew RuntimeException("the value of the dialect property in configuration.xml is not defined : "+ configuration.getVariables().getProperty("dialect"));

}

Dialect dialect =null;

switch(databaseType){

case MYSQL:

dialect =new MySql5Dialect();



}



String originalSql = (String)metaStatementHandler.getValue("delegate.boundSql.sql");

metaStatementHandler.setValue("delegate.boundSql.sql", dialect.getLimitString(originalSql, rowBounds.getOffset(), rowBounds.getLimit()) );

metaStatementHandler.setValue("delegate.rowBounds.offset", RowBounds.NO_ROW_OFFSET );

metaStatementHandler.setValue("delegate.rowBounds.limit", RowBounds.NO_ROW_LIMIT );

if(log.isDebugEnabled()){

log.debug("生成分頁SQL : "+ boundSql.getSql());

}

return invocation.proceed();

}



@Override

public Object plugin(Object target) {

return Plugin.wrap(target, this);

}



@Override

publicvoid setProperties(Properties properties) {

}



}

?

里面最重要的三條語句:

metaStatementHandler.setValue("delegate.boundSql.sql", dialect.getLimitString(originalSql, rowBounds.getOffset(), rowBounds.getLimit()) );

metaStatementHandler.setValue("delegate.rowBounds.offset", RowBounds.NO_ROW_OFFSET );

metaStatementHandler.setValue("delegate.rowBounds.limit", RowBounds.NO_ROW_LIMIT );                                           改別要執(zhí)行的sql語句,現(xiàn)在新設(shè)置的sql語句是物理分頁的,所以現(xiàn)在不再需要mybatis進行額外的操作了,所以把rowBounds的偏移量恢復(fù)為初始值(offet:0,limit:Integer.max) 為了指定數(shù)據(jù)庫版本,在mybatis全局配置文件設(shè)置dialect值 <properties>

<property name="dialect" value="mysql"/>

</properties>

<plugins>

<plugin interceptor="study.mybatis.interceptor.PaginationInterceptor">

</plugin>

</plugins>

完整代碼請用svn從下面鏈接檢出查看:

svn checkout?http://20110311start.googlecode.com/svn/trunk/

下個系列將會講下緩存的擴展應(yīng)用。     -----------------------------分隔線---------------------------------------------

最近有朋友用mybatis和spring整合的時候如果按照下列方式發(fā)現(xiàn)dialect屬性不能設(shè)置成功:

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="dataSource" /><property name="typeAliasesPackage" value="com.***.web.domain" /><property name="plugins"><array><ref bean="paginationInterceptor"/></array></property><property name="configurationProperties"><props><prop key="dialect">mysql</prop></props></property> </bean>

?

這個問題是org.mybatis.spring.SqlSessionFactoryBean這個代碼里有個bug(244行,或者不是bug,是作者不想這么做法),如果感興趣可以看下源碼。配置文件做下如下修改:

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="dataSource" /><property name="typeAliasesPackage" value="com.***.web.domain" /><property name="plugins"><array><ref bean="paginationInterceptor"/></array></property><!-- 這里不要,注釋掉<property name="configurationProperties"><props><prop key="dialect">mysql</prop></props></property>--><!-- 加上這個屬性 --><property name="configLocation" value="classpath:Mybatis_Configuration.xml"/> </bean>

?

Mybatis_Configuration.xml的配置如下:

1 <?xml version="1.0" encoding="UTF-8" ?>
2 <!DOCTYPE configuration
3 PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
4 "http://mybatis.org/dtd/mybatis-3-config.dtd">
5 <configuration>
6
7   <properties>
8     <property name="dialect" value="oracle"/>
9   </properties>
10
11 </configuration>

?

原創(chuàng)文章,轉(zhuǎn)載請注明出處,謝謝!

分類:?java 標簽:?mybatis分頁 mybatis 綠色通道:?好文要頂?關(guān)注我?收藏該文與我聯(lián)系? 海鳥
關(guān)注 - 2
粉絲 - 7 +加關(guān)注 0 0 (請您對文章做出評價) ??博主上一篇:DriverManager怎樣查找當(dāng)前Driver
??博主下一篇:java中顯示設(shè)置實例為null多余嗎 posted @?2011-08-09 14:07?海鳥?閱讀(8189) 評論(6)?編輯?收藏

評論列表 回復(fù)引用 #1樓?2011-09-07 09:30?kugua-? delegate.rowBounds.offset 是在哪定義的? 為什么要設(shè)置這個屬性呢? 支持(0)反對(0) 回復(fù)引用 #2樓[樓主]?2011-09-07 11:21?海鳥? @kugua-
我們調(diào)用分頁的API一般是這樣的:
?
1 List l = session.selectList("users.selectUsers", user,new?RowBounds(2, 1));

mybatis默認情況下全部查詢出來后再截取當(dāng)前頁的記錄。可是如果我們自己寫了個分頁插件的情況下采用了物理分頁,查詢出來的記錄就是當(dāng)前頁的內(nèi)容。所以現(xiàn)在要告訴mybatis不再對結(jié)果進行加工,所以要重置為不分頁的設(shè)置:
?
1 2 3 metaStatementHandler.setValue("delegate.rowBounds.offset", RowBounds.NO_ROW_OFFSET ); metaStatementHandler.setValue("delegate.rowBounds.limit", RowBounds.NO_ROW_LIMIT ); 

這兩條語句就是用反射機制設(shè)置,相當(dāng)于:
?
1 2 3 delegate.getRowBounds.setLimit(RowBounds.NO_ROW_LIMIT); delegate.getRowBounds.setOffset(RowBounds.NO_ROW_OFFSET);
支持(0)反對(0)

轉(zhuǎn)載于:https://www.cnblogs.com/samkin/articles/2864593.html

總結(jié)

以上是生活随笔為你收集整理的转:mybatis - 分页功能的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。