Java中的Cursor使用詳解
最近看代碼,有一段代碼涉及到Cursor,感覺寫法挺有意思的。注意是Cursor,而不是Consumer,我之前把兩個(gè)搞混了,看代碼看的渾渾噩噩的。
這里說的Cursor,一般來是JDBC的工具,像我在項(xiàng)目中的mybatis里面的Cursor。
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by FernFlower decompiler) // package org.apache.ibatis.cursor; import java.io.Closeable; public interface Cursor<T> extends Closeable, Iterable<T> { boolean isOpen(); boolean isConsumed(); int getCurrentIndex(); }
Cursor用途一般就是遍歷查詢結(jié)果集,比如下面
try(Cursor<AssetDO> cursor = assetMapper.streamQueryAssetByRange(maps)) { Iterator<AssetDO> iterator = cursor.iterator(); List<AssetDO> list = new LinkedList<>(); while (iterator.hasNext()){ list.add(iterator.next()); if(tempCount % limitCount == 0){ consumer.accept(list); list = new ArrayList<>(); } assetCount++; tempCount++; } if(CollectionUtil.isNotEmpty(list)) { consumer.accept(list); } } catch (IOException e) { log.info(e.getMessage(), e); }
實(shí)際上不用這個(gè)我們也可以遍歷,直接查出結(jié)果集來遍歷,為什么還要用Cursor在包裝一層來遍歷。
實(shí)際上這個(gè)在數(shù)據(jù)量小的時(shí)候,實(shí)際上沒啥差距,甚至普通的查詢遍歷可讀性更強(qiáng)。主要是面對(duì)數(shù)據(jù)量大的時(shí)候,也就是大數(shù)據(jù)集處理會(huì)體現(xiàn)出的優(yōu)勢(shì),主要的原理就是它可以逐行讀取數(shù)據(jù),而不是先把整個(gè)結(jié)果集讀取加載到內(nèi)存中,這樣就可以節(jié)省內(nèi)存空間。實(shí)際上我們項(xiàng)目就會(huì)涉及到一個(gè)盤點(diǎn)的功能,當(dāng)涉及到范圍廣數(shù)據(jù)量大的情況,Cursor就很適合這種情況。
這邊說一下Cursor的優(yōu)勢(shì):
- 大數(shù)據(jù)集處理:
逐行讀取:
Cursor允許你逐行讀取數(shù)據(jù),而不是一次性將整個(gè)結(jié)果集加載到內(nèi)存中。這對(duì)于處理非常大的數(shù)據(jù)集特別有用,因?yàn)樗梢詷O大地減少內(nèi)存消耗,避免內(nèi)存溢出。
分頁處理: 可以根據(jù)需要處理一部分?jǐn)?shù)據(jù),然后再讀取下一部分,這樣可以實(shí)現(xiàn)數(shù)據(jù)的分頁加載。
- 流控制:
動(dòng)態(tài)讀取: 你不需要在開始時(shí)等待整個(gè)結(jié)果集從數(shù)據(jù)庫讀取完畢,可以立即處理第一條記錄,對(duì)于響應(yīng)時(shí)間非常重要的應(yīng)用場(chǎng)景非常有利。
動(dòng)態(tài)改變查詢: 使用Cursor可以動(dòng)態(tài)改變查詢條件或者操作,而不是一次性固定查詢數(shù)據(jù)。
- 并發(fā)控制:
提高并發(fā)性: Cursor可以提高數(shù)據(jù)庫多用戶并發(fā)訪問的性能,因?yàn)槊總€(gè)用戶只會(huì)鎖定當(dāng)前正在讀取的行,而不是整個(gè)表或表的很大一部分。
事務(wù)一致性: Cursor可以與數(shù)據(jù)庫事務(wù)很好地結(jié)合,確保在事務(wù)處理期間數(shù)據(jù)的完整性和一致性。
- 減少網(wǎng)絡(luò)流量:
在客戶端與數(shù)據(jù)庫服務(wù)器之間的網(wǎng)絡(luò)通信中,Cursor可以減少網(wǎng)絡(luò)流量,因?yàn)樗鹦凶x取數(shù)據(jù),而不是一次性傳輸整個(gè)結(jié)果集。
代碼上去看Cursor帶代碼,首先是接口,接口是相當(dāng)于一個(gè)規(guī)定,你可以根據(jù)這個(gè)規(guī)定寫出一個(gè)更好的實(shí)現(xiàn)方案,這里就先看一下Cursor接口的三個(gè)方法:
isOpen()方法用于檢查游標(biāo)是否已經(jīng)打開。如果游標(biāo)已經(jīng)打開并且可以使用,該方法返回true,否則返回false。
isConsumed()方法用于檢查游標(biāo)中的所有數(shù)據(jù)是否都已經(jīng)被處理。如果游標(biāo)中的所有數(shù)據(jù)都已經(jīng)被讀取或者使用,該方法返回true,否則返回false。
getCurrentIndex()方法返回當(dāng)前游標(biāo)位于結(jié)果集的索引位置。這個(gè)索引位置從0開始計(jì)數(shù),它可以用來跟蹤已經(jīng)處理的行數(shù)或條目數(shù)
這三個(gè)方法我們可以判斷是否數(shù)據(jù)集,一行一行讀取是否能讀完,當(dāng)前索引,這對(duì)我們遍歷很有用,本身這個(gè)接口就是Iterable迭代器。
一般我們選擇的ORM都會(huì)對(duì)應(yīng)這個(gè)接口有對(duì)應(yīng)的某人實(shí)現(xiàn)DefaultCursor。這個(gè)我么們可以通過idea工具來查看,總之當(dāng)遇到一個(gè)大數(shù)據(jù)集加載導(dǎo)致占用內(nèi)存飆升甚至內(nèi)存溢出,可以考慮采用這個(gè)Cursor工具,來減小內(nèi)存占用以及Cursor的并發(fā)提高效率算短時(shí)間。
值得注意的是Cursor用使用try-with-resources語句來自動(dòng)關(guān)閉它,不要占用寶貴的數(shù)據(jù)庫連接。
到此這篇關(guān)于Java中的Cursor使用詳解的文章就介紹到這了,更多相關(guān)Java Cursor使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
如何在SpringBoot項(xiàng)目中使用Oracle11g數(shù)據(jù)庫
這篇文章主要介紹了在SpringBoot項(xiàng)目中使用Oracle11g數(shù)據(jù)庫的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06使用Spring?Cloud?Stream處理Java消息流的操作流程
Spring?Cloud?Stream是一個(gè)用于構(gòu)建消息驅(qū)動(dòng)微服務(wù)的框架,能夠與各種消息中間件集成,如RabbitMQ、Kafka等,今天我們來探討如何使用Spring?Cloud?Stream來處理Java消息流,需要的朋友可以參考下2024-08-08數(shù)據(jù)結(jié)構(gòu)與算法之并查集(不相交集合)
并查集是一種挺高效的數(shù)據(jù)結(jié)構(gòu)。實(shí)現(xiàn)簡(jiǎn)單,只是所有元素統(tǒng)一遵從一個(gè)規(guī)律所以讓辦事情的效率高效起來。這篇文章主要介紹了數(shù)據(jù)結(jié)構(gòu)與算法——并查集(不相交集合),需要的朋友可以參考下2019-11-11關(guān)于JDK8升級(jí)17及springboot?2.x升級(jí)3.x詳細(xì)指南
這篇文章主要介紹了關(guān)于JDK8升級(jí)17及springboot?2.x升級(jí)3.x的相關(guān)資料,還討論了JPA包路徑從javax改為jakarta,以及Spring?Boot版本升級(jí)和Redis配置調(diào)整等,需要的朋友可以參考下2025-01-01Java使用Apache Commons高效處理CSV文件的操作指南
在 Java 開發(fā)中,CSV(Comma-Separated Values,逗號(hào)分隔值)是一種常見的數(shù)據(jù)存儲(chǔ)格式,廣泛用于數(shù)據(jù)交換和簡(jiǎn)單的存儲(chǔ)任務(wù),本文將介紹Java使用Apache Commons高效處理CSV文件的操作指南,需要的朋友可以參考下2025-03-03