A. MyBatis怎樣實現MySQL動態分頁
回記錄行的偏移量,第二個參數指定返回記錄行的最大數量。在mybatis 中,只需要在相 應的查詢語句後,加上limit 子句,即可實現物理分頁。如下,以 一個只有欄位id,name,age 的表為例。該配置會根據傳入的 hashmap,如果含有鍵start 和鍵end,...
B. mybatis分頁-RowBounds - 草稿
MyBatis中使用RowBounds對查詢結果集進行分頁,具體操作過程:MyBatis可以使用RowBounds逐頁載入表數據。RowBounds對象可以使用offset和limit參數來構建。參數offset表示開始位置,而limit表示要取的記錄的數目
映射文件:
<select id="findAllUsers" resultType="User">
select id,name,gender from t_user
</select>
映射介面中:
public List<User> findAllUsers(RowBounds rowBounds);
測試方法:
@Test
public void test_findAllUsers2(){
SqlSession sqlSession = null;
try {
sqlSession = MyBatisSqlSessionFactory.openSession();
SpecialMapper mapper = sqlSession.getMapper(SpecialMapper.class);
//表示從第幾條數據開始
int offset = 0;
//連續取出幾條數據
int limit = 5;
RowBounds rowBounds = new RowBounds(offset, limit);
List<User> list = mapper.findAllUsers(rowBounds);
list.forEach(System.out::println);
} catch (Exception e) {
e.printStackTrace();
}
}
注意,若規定每頁5條數據,要展示第二頁,使用offset=5,limit=5
備註:通過以上例子,很明顯的看出,在分頁的時候,我們是把所有的數據都查詢出來,然後通過RowBounds進行在內存分頁.通過源碼查看,也是通過ResuleSet結果集進行分頁;
但是其實Mybatis的分頁是基於內存的分頁(查出所有記錄再按偏移量和limit取結果),在大數據量的情況下這樣的分頁效率會很低,一般情況下我們會使用myts的分頁輔助工具來完成分頁
總結:
1:邏輯分頁 內存開銷比較大,在數據量比較小的情況下效率比物理分頁高;在數據量很大的情況下,內存開銷過大,容易內存溢出,不建議使用
2:物理分頁 內存開銷比較小,在數據量比較小的情況下效率比邏輯分頁還是低,在數據量很大的情況下,建議使用物理分頁
C. MyBatis解析
從命名上可以看出,這個是一個 Builder 模式的,用於創建 SqlSessionFactory 的類。SqlSessionFactoryBuilder 根據配置來構造 SqlSessionFactory。其中配置方式有兩種:
mybatis-config.xml 就是我們的配置文件:
Java Config 相比較 XML 文件的方式而言,會有一些限制。比如修改了配置文件需要重新編譯,註解方式沒有 XML 配置項多等。所以,業界大多數情況下是選擇 XML 文件的方式。但到底選擇哪種方式,這個要取決與自己團隊的需要。比如,項目的 SQL 語句不復雜,也不需要一些高級的 SQL 特性,那麼 Java Config 則會更加簡潔一點;反之,則可以選擇 XML 文件的方式。
創建配置文件解析器XMLConfigBuilder
解析mybatis-config.xml里的配置為Configuration對象,Mybatis的全局配置對象。
XMLConfigBuilder#parseConfiguration解析mapper下的xml
XMLMapperBuilder#bindMapperForNamespace,根據xml里的 namespace 反射出 mapper介面 的 class,如果有mapper介面,則把該mapper介面的class添加到Configuration的mapperRegistry里。
如果該介面已經注冊,則拋出已經綁定的異常。
為該介面注冊MapperProxyFactory,但這里只是注冊其創建MapperProxy的工廠,並不是創建MapperProxy。
如果Mapper對應的xml資源未載入,觸發xml的綁定操作,將xml中的sql語句與Mapper建立關系。
addMapper方法,只是為**Mapper創建對應對應的MapperProxyFactory。
根據Mapper介面與SqlSession創建MapperProxy對象。
根據介面類獲取MapperProxyFactory。
調用MapperProxyFactory的newInstance創建MapperProxy對象。
SqlSessionFactory 顧名思義,是用於生產 SqlSession 的工廠。 通過如下的方式來獲取 SqlSession 實例:
SqlSession 包含了執行 SQL 的所有的方法。以下是示例:
當然,下面的方式可以做到類型安全:
MapperProxy是MapperProxyFactory使用SqlSession創建出來的。所以MapperProxy中包含SqlSession。
可以看到MapperProxy調用invoke方法,進而調用MapperMethod的execute(),這些MapperMethod就是和你要執行的命令相關,比如執行select語句,則會通過SqlSession的select()方法,最終調用到Executor的query方法。Executor會再協調另外三個核心組件。
MapperProxy:
MapperMethod:
插件的構建:
談原理首先要知道StatementHandler,ParameterHandler,Result Handler都是代理,他們是Configuration創建,在創建過程中會調用interceptorChain.pluginAll()方法,為四大組件組裝插件(再底層是通過Plugin.wrap(target,XX, new Plugin( interceptor))來來創建的)。
插件鏈是何時構建的:
在執行SqlSession的query或者update方法時,SqlSession會通過Configuration創建Executor代理,在創建過程中就調用interceptor的pluginAll方法組裝插件。然後executor在調用doQuery()方法的時候,也會調用Configuration的newStatementHandler方法創建StatemenHandler(和上面描述的一樣,這個handler就是個代理,也是通過interceptorChain的pluginAll方法構建插件)
插件如何執行:
以statementhandler的prepare方法的插件為例,正如前面所說,statementhandler是一個proxy,執行他的prepare方法,將調用invokeHandler的invoke方法,而invokeHandler就是Plugin.wrap(target, xxx, new Plugin(interceptor))中的第三個參數,所以很自然invokeHanlder的invoke的方法最終就會調用interceptor對象的intercept方法。
Mybatis的插件配置在configuration內部,初始化時,會讀取這些插件,保存於Configuration對象的InterceptorChain中。
org.apache.ibatis.plugin.InterceptorChain.java源碼。
上面的for循環代表了只要是插件,都會以責任鏈的方式逐一執行,所謂插件,其實就類似於攔截器。
插件的編寫
插件必須實現org.apache.ibatis.plugin.Interceptor介面。
-intercept()方法:執行攔截內容的地方,攔截目標對象的目標方法的執行
-plugin()方法:決定是否觸發intercept()方法。 作用:包裝目標對象,包裝就是為目標對象創建一個代理對象
-setProperties()方法:給自定義的攔截器傳遞xml配置的屬性參數。將插件注冊時的property屬性設置進來
下面自定義一個攔截器:
為什麼要寫Annotation註解?註解都是什麼含義?
Mybatis規定插件必須編寫Annotation註解,是必須,而不是可選。@Intercepts註解:裝載一個@Signature列表,一個@Signature其實就是一個需要攔截的方法封裝。那麼,一個攔截器要攔截多個方法,自然就是一個@Signature列表。
type = Executor.class, method = "query", args = { MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class }
解釋:要攔截Executor介面內的query()方法,參數類型為args列表。
Plugin.wrap(target, this)是干什麼的?
使用JDK的動態代理,給target對象創建一個delegate代理對象,以此來實現方法攔截和增強功能,它會回調intercept()方法。
Mybatis可以攔截哪些介面對象?
Mybatis只能攔截ParameterHandler、ResultSetHandler、StatementHandler、Executor共4個介面對象內的方法。
重新審視interceptorChain.pluginAll()方法:該方法在創建上述4個介面對象時調用,其含義為給這些介面對象注冊攔截器功能,注意是注冊,而不是執行攔截。
攔截器執行時機:plugin()方法注冊攔截器後,那麼,在執行上述4個介面對象內的具體方法時,就會自動觸發攔截器的執行,也就是插件的執行。
Invocation
可以通過invocation來獲取攔截的目標方法,以及執行目標方法。
分頁插件原理
由於Mybatis採用的是邏輯分頁,而非物理分頁,那麼,市場上就出現了可以實現物理分頁的Mybatis的分頁插件。 要實現物理分頁,就需要對String sql進行攔截並增強,Mybatis通過BoundSql對象存儲String sql,而BoundSql則由StatementHandler對象獲取。
因此,就需要編寫一個針對StatementHandler的query方法攔截器,然後獲取到sql,對sql進行重寫增強。
D. 關於mybatis物理分頁的問題,求大神幫忙看看
原因在這句異常:
org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 10
你使用了selectOne方法,這個方法返回一條數據,但是你的find中查詢出了10條數據,這塊改一下就好了
E. MyBatis怎樣實現MySQL動態分頁
回記錄行的偏移量,第二個參數指定返回記錄行的最大數量。在mybatis 中,只需要在相 應的查詢語句後,加上limit 子句,即可實現物理分頁。如下,以 一個只有欄位id,name,age 的表為例。該配置會根據傳入的 hashmap,如果含有鍵start 和鍵end,那麼即通過mybatis 強大的 動態sql,生成含有mysql 分頁的sql語句。 select * from users limit #{start},#{end}
二、myts 簡介
mybatis,前稱ibatis,後改名為mybatis,截止本文成文,最新 版本是3.0.6。它和hibernate 是java世界使用最多的兩種orm 框 架。hibernate 理念最為先進,完全實現面向對象的資料庫編程,不需要掌握sql 語句,即可實現資料庫操作,能夠節省開發人員編 寫大量sql語句的時間。但是,hibernate 在處理多表關聯時,可 能會出現n+1 問題,性能會有較大影響,要解決性能問題,需要較 深的hibernate 知識和項目經驗。mybatis 需要自己寫sql 語句, 開發效率不如hibernate,很難做到底層多資料庫的通用。但對程 序員來說有更高的可控性,可以更容易的對sql 語句進行優化,提 高效率。
在開發中直接使用jdbc 一個非常普遍的問題就是動態sql。如果 參數值、參數本身和數據列都是動態sql,通常的解決方法就是寫很多if-else 條件語句和字元串連接。而mybatis 通過ognl 提供 了一套非常清晰的方法來解決動態sql 的問題。
F. mybatis分頁查詢怎麼做
一、內存分頁,使用RowBounds類,但這種方式不推薦,基本不用,所以此方式集成省略。
二、自定義實現,代碼量比較少,簡單,比較靈活。以下為具體的集成步驟:
1、在User.xml中加入select節點,並組裝分頁SQ
G. 如何使用 mybatis 實現分頁
1、親Mybatis是自己寫Sql語句啊,和Hibernate不一樣。
2、如何知道上面的,你還要知道MySql有一個分頁語句叫limit,如:limit(1,10);前面一個參數是起始未知,後面一個是查詢多少個。
3、Oracle的分頁方法是嵌套子查詢,需要用到rownum這個屬性
Sql
Server是Top。
分頁例子:
Oracle
select
*
from
(select
emp.*,rownum
rn
from
emp
where
rownum<9)
where
rn>3;
MySql
select
*
from
emp
limit
startIndex,maxNum
H. mybatis怎麼實現物理分頁查詢語句
物理分頁:
直接用jdbc完成:使用滾動結果集 ?
優點:跨資料庫 ? ? 缺點:性能低
2.使用資料庫本身提供的分頁操作:使用每一個資料庫特定的分頁函數
優點:性能高 ? ? ? 缺點:不能跨資料庫
I. Mybatis分頁對比MybatisPlus分頁
Mybatis使用內存分頁
Mybatis使用RowBounds對象進行分頁,它是針對ResultSet結果集執行的內存分頁,而非物理分頁。可以在sql內直接書寫帶有物理分頁的參數來完成物理分頁功能,也可以使用分頁插件來完成物理分頁。
分頁插件的基本原理是使用Mybatis提供的插件介面,實現自定義插件,在插件的攔截方法內攔截待執行的sql,然後重寫sql,根據dialect方言,添加對應的物理分頁語句和物理分頁參數。
————————————————
MybatisPlus是物理分頁
基本步驟是:
1 原生SQL解析
2 判斷有無page分頁對象。沒有對象就直接進行SQL操作,有對象就繼續分頁解析
3 count語句優化。根據SQL條件進行count優化,這點不同於傳統的 select count(1) from (你的 業務 SQL) 做下簡單的封裝,詳細源碼可以自己看,或者列印出執行的SQL可以清楚的看到
4 通過count數量和之前前端傳遞來的分頁pageNum和pageSize對SQL進行拼接
5最終執行拼接完整的SQL實現分頁處理
總結:mybatis的是內存分頁,全查出來丟在內存中,這樣子很不好! 現在大面積使用的插件MybatisPlus是物理分頁,先查詢總數(不像網上很多人說的只是簡單外包一層計算count),再根據分頁參數瓶裝SQL然後執行分頁查詢
J. oracle下mybatis一對多的映射關系怎麼分頁
mybatis的物理分頁:mybatis-paginator
github上有一個專門針對mybatis的物理分頁開源項目:mybatis-paginator,兼容目前絕大多數主流資料庫,十分好用,下面是使用步驟:
環境:struts2 + spring + mybatis
一、pom.xml中添加依賴項
View Code
二、mybatis映射文件中按常規寫sql語句
View Code
如果使用mybatis-spring來整合mybatis,sqlSessionFactory參考下面修改(主要是載入分頁插件)
View Code
三、服務層基類
View Code
四、具體的服務層子類調用
View Code
服務層就處理完了,接下來看Action層
五、Action基類
View Code
註:約定分頁時,url類似 /xxx.action?pageIndex=N
六、具體的Action子類調用
View Code
七、前端頁面
View Code
解釋:jquery的分頁插件,網上一搜索一大堆,我用的是jquery.simplePagination,pageIndex、pageIndex、{pageSize}...包括list,這些屬性都是後台Action中的model屬性
後記:
github上還有另一款mybatis的分頁插件:Mybatis-PageHelper 也十分好用,使用說明參考:http://git.oschina.net/free/Mybatis_PageHelper/blob/master/wikis/HowToUse.markdown
使用示例:
View Code
mybatis-config.xml中的配置:
View Code