- 資訊首頁(yè) > 互聯(lián)網(wǎng) > 經(jīng)驗分享 >
- 新技能MyBatis千萬(wàn)數據表,快速分頁(yè)!
基本概念流式查詢(xún)指的是查詢(xún)成功后不是返回一個(gè)集合而是返回一個(gè)迭代器,應用每次從迭代器取一條查詢(xún)結果。流式查詢(xún)的好處是能夠降低內存使用。如果沒(méi)有流式查詢(xún),我們想要從數據庫取 1000 萬(wàn)條記錄而又沒(méi)有足夠的內存時(shí),就不得不分頁(yè)查詢(xún),而分頁(yè)查詢(xún)效率取決于表設計,如果設計的不好,就無(wú)法執行高效的分頁(yè)查詢(xún)。因此流式查詢(xún)是一個(gè)數據庫訪(fǎng)問(wèn)框架必須具備的功能。流式查詢(xún)的過(guò)程當中,數據庫連接是保持打開(kāi)狀態(tài)的,因此要注意的是:執行一個(gè)流式查詢(xún)后,數據庫訪(fǎng)問(wèn)框架就不負責關(guān)閉數據庫連接了,需要應用在取完數據后自己關(guān)閉。
MyBatis 提供了一個(gè)叫
org.apache.ibatis.cursor.Cursor的接口類(lèi)用于流式查詢(xún),這個(gè)接口繼承了 java.io.Closeable 和 java.lang.Iterable 接口,由此可知:
1、 Cursor 是可關(guān)閉的;2、 Cursor 是可遍歷的。除此之外,Cursor 還提供了三個(gè)方法:
1、 isOpen():用于在取數據之前判斷 Cursor 對象是否是打開(kāi)狀態(tài)。只有當打開(kāi)時(shí) Cursor 才能取數據;
2、 isConsumed():用于判斷查詢(xún)結果是否全部取完。
3、 getCurrentIndex():返回已經(jīng)獲取了多少條數據
因為 Cursor 實(shí)現了迭代器接口,因此在實(shí)際使用當中,從 Cursor 取數據非常簡(jiǎn)單:
cursor.forEach(rowObject -> {…});
我們舉個(gè)實(shí)際例子。下面是一個(gè) Mapper 類(lèi):
方法 scan() 是一個(gè)非常簡(jiǎn)單的查詢(xún)。通過(guò)指定 Mapper 方法的返回值為 Cursor 類(lèi)型,MyBatis 就知道這個(gè)查詢(xún)方法一個(gè)流式查詢(xún)。然后我們再寫(xiě)一個(gè) SpringMVC Controller 方法來(lái)調用 Mapper(無(wú)關(guān)的代碼已經(jīng)省略):
上面的代碼中,fooMapper 是 @Autowired 進(jìn)來(lái)的。注釋 1 處調用 scan 方法,得到 Cursor 對象并保證它能最后關(guān)閉;2 處則是從 cursor 中取數據。上面的代碼看上去沒(méi)什么問(wèn)題,但是執行 scanFoo0() 時(shí)會(huì )報錯:
java.lang.IllegalStateException: A Cursoris already closed.
這是因為我們前面說(shuō)了在取數據的過(guò)程中需要保持數據庫連接,而 Mapper 方法通常在執行完后連接就關(guān)閉了,因此 Cusor 也一并關(guān)閉了。所以,解決這個(gè)問(wèn)題的思路不復雜,保持數據庫連接打開(kāi)即可。我們至少有三種方案可選。
我們可以用 SqlSessionFactory 來(lái)手工打開(kāi)數據庫連接,將 Controller 方法修改如下:
上面的代碼中,1 處我們開(kāi)啟了一個(gè) SqlSession (實(shí)際上也代表了一個(gè)數據庫連接),并保證它最后能關(guān)閉;2 處我們使用 SqlSession 來(lái)獲得 Mapper 對象。這樣才能保證得到的 Cursor 對象是打開(kāi)狀態(tài)的。
在 Spring 中,我們可以用 TransactionTemplate 來(lái)執行一個(gè)數據庫事務(wù),這個(gè)過(guò)程中數據庫連接同樣是打開(kāi)的。代碼如下:
上面的代碼中,1 處我們創(chuàng )建了一個(gè) TransactionTemplate 對象(此處 transactionManager 是怎么來(lái)的不用多解釋?zhuān)疚募僭O讀者對 Spring 數據庫事務(wù)的使用比較熟悉了)。2 處執行數據庫事務(wù),而數據庫事務(wù)的內容則是調用 Mapper 對象的流式查詢(xún)。注意這里的 Mapper 對象無(wú)需通過(guò) SqlSession 創(chuàng )建。
這個(gè)本質(zhì)上和方案二一樣,代碼如下:
它僅僅是在原來(lái)方法上面加了個(gè) @Transactional 注解。這個(gè)方案看上去最簡(jiǎn)潔,但請注意 Spring 框架當中注解使用的坑:只在外部調用時(shí)生效。在當前類(lèi)中調用這個(gè)方法,依舊會(huì )報錯。
以上是三種實(shí)現 MyBatis 流式查詢(xún)的方法。
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自本網(wǎng)站內容采集于網(wǎng)絡(luò )互聯(lián)網(wǎng)轉載等其它媒體和分享為主,內容觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如侵犯了原作者的版權,請告知一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容,聯(lián)系我們QQ:712375056,同時(shí)歡迎投稿傳遞力量。
Copyright ? 2009-2022 56dr.com. All Rights Reserved. 特網(wǎng)科技 特網(wǎng)云 版權所有 特網(wǎng)科技 粵ICP備16109289號
域名注冊服務(wù)機構:阿里云計算有限公司(萬(wàn)網(wǎng)) 域名服務(wù)機構:煙臺帝思普網(wǎng)絡(luò )科技有限公司(DNSPod) CDN服務(wù):阿里云計算有限公司 百度云 中國互聯(lián)網(wǎng)舉報中心 增值電信業(yè)務(wù)經(jīng)營(yíng)許可證B2
建議您使用Chrome、Firefox、Edge、IE10及以上版本和360等主流瀏覽器瀏覽本網(wǎng)站