Mybatis游標查詢大量數(shù)據(jù)方式
Mybatis游標查詢大量數(shù)據(jù)
對大量數(shù)據(jù)進行處理時,為防止內(nèi)存泄漏情況發(fā)生,所以采用mybatis plus游標方式進行數(shù)據(jù)查詢處理,當查詢百萬級的數(shù)據(jù)的時候,使用游標可以節(jié)省內(nèi)存的消耗,不需要一次性取出所有數(shù)據(jù),可以進行逐條處理或逐條取出部分批量處理
mapper層
- 使用Cursor類型進行數(shù)據(jù)接收
- @Options,fetchSize設置為Integer最小值
- @Select,寫查詢sql
@Options(resultSetType = ResultSetType.FORWARD_ONLY, fetchSize = Integer.MIN_VALUE) @Select("select domain from illegal_domain where icpstatus != #{icpstatus}") Cursor<IllegalDomain> getDayJobDomain(@Param("icpstatus") Integer icpstatus);
service層
Cursor<IllegalDomain> domainList = illegalDomainMapper.getDayJobDomain(1);
數(shù)據(jù)處理
forEach方式
domainList.forEach(illegalDomain -> { ? ? //處理邏輯,根據(jù)業(yè)務需求自行完成 ? ? Future<IcpStatusVo> future = checkIcpThreadPool.submit(new IcpCheckThread(illegalDomain.getDomain(), configMap)); ? ? results.add(future); });
迭代器
Iterator<IllegalDomain> iter = domainList.iterator(); while (iter.hasNext()) { ? ? <!--// Fetch next 10 employees--> ? ? <!--for(int i = 0; i<10 && iter.hasNext(); i++) {--> ? ? <!-- ? ?smallChunk.add(iter.next());--> ? ? <!--}--> ? ?? ? ? //處理邏輯,根據(jù)業(yè)務需求自行完成 ? ? Future<IcpStatusVo> future = checkIcpThreadPool.submit(new IcpCheckThread(illegalDomain.getDomain(), configMap)); ? ? results.add(future); }
資源釋放
使用完畢后,在finally塊釋放資源,否則游標不關閉也可能會導致內(nèi)存溢出問題
try{ ? ? //your code ? ?? } catch (Exception e) { ? ? log.error(e); } finally { ? ? if(null != domainList){ ? ? ? ? try { ? ? ? ? ? ? domainList.close(); ? ? ? ? } catch (IOException e) { ? ? ? ? ? ? e.printStackTrace(); ? ? ? ? } ? ? } }
Mybatis游標使用總結
當查詢百萬級的數(shù)據(jù)的時候,查詢出所有數(shù)據(jù)并放入內(nèi)存中時會發(fā)生OOM(OutOfMemoryException),使用游標可以節(jié)省內(nèi)存的消耗,不需要一次性取出所有數(shù)據(jù),可以進行逐條處理或逐條取出部分批量處理,在此場景下就可以使用游標的概念來解決這個問題。
什么是游標
游標(Cursor)是處理數(shù)據(jù)的一種方法,為了查看或者處理結果集中的數(shù)據(jù),游標提供了在結果集中一次一行或者多行前進或向后瀏覽數(shù)據(jù)的能力。
Demo:
// 第一種 @Options(resultSetType = ResultSetType.FORWARD_ONLY) @Select("SELECT * FROM department WHERE status = 0") List<DepartmentEntity> queryDepartmentAll(); // 第二種 在Mybatis-3.4.0版本中,不支持@select注解,在3.4.1版本中已經(jīng)修復: @Options(resultSetType = ResultSetType.FORWARD_ONLY) @Select("SELECT * FROM department WHERE status = 0") Cursor<Employee> cursorQueryDepartmentAll();
@Service public class DepartmentServiceImpl implements DepartmentService { private static final Logger LOG = LoggerFactory.getLogger(DepartmentServiceImpl.class); @Autowired private DepartmentDao departmentDao; @Autowired private SqlSessionTemplate sqlSessionTemplate; public List<DepartmentDTO> getDepartmentList(DepartmentSearchParam param) { Cursor<Object> cursor = null; SqlSession sqlSession = null; try { sqlSession = sqlSessionTemplate.getSqlSessionFactory().openSession(); cursor = sqlSession.selectCursor(DepartmentDao.class.getName() + ".queryDepartmentAll"); cursor.forEach(e -> { // 處理邏輯 }); // 也可以使用迭代器:Iterator<Object> iterator = cursor.iterator(); } catch (Exception e) { e.printStackTrace(); } finally { if (null != cursor) { try { cursor.close(); } catch (Exception e) { LOG.error(e.getMessage(), e); } } if (null != sqlSession) { try { sqlSession.close(); } catch (Exception e) { LOG.error(e.getMessage(), e); } } } } }
ResultSet.TYPE_FORWORD_ONLY
結果集的游標只能向下滾動。ResultSet.TYPE_SCROLL_INSENSITIVE
結果集的游標可以上下移動,當數(shù)據(jù)庫變化時,當前結果集不變。ResultSet.TYPE_SCROLL_SENSITIVE
返回可滾動的結果集,當數(shù)據(jù)庫變化時,當前結果集同步改變。
注意:游標是可以前后移動的。如果resultSetType = TYPE_SCROLL_INSENSITIVE ,就是設置游標就可以前后移動。
Mybatis為了保證可以前后移動,Mybatis會把之前查詢的數(shù)據(jù)一直保存在內(nèi)存中。
所以并不能根本解決OOM,所以我們這里需要設置為@Options(resultSetType = ResultSetType.FORWARD_ONLY)(其實默認就是ResultSetType.FORWARD_ONLY)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
解決spring mvc 多數(shù)據(jù)源切換,不支持事務控制的問題
下面小編就為大家?guī)硪黄鉀Qspring mvc 多數(shù)據(jù)源切換,不支持事務控制的問題。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-09-09Java Http請求傳json數(shù)據(jù)亂碼問題的解決
這篇文章主要介紹了Java Http請求傳json數(shù)據(jù)亂碼問題的解決,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-09-09springMvc和mybatis-plus中枚舉值和字段的映射
這篇文章主要為大家介紹了springMvc和mybatis-plus中枚舉值和字段的映射示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-05-05線程池ThreadPoolExecutor并行處理實現(xiàn)代碼
這篇文章主要介紹了線程池ThreadPoolExecutor并行處理實現(xiàn)代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-11-11Java語言----三種循環(huán)語句的區(qū)別介紹
下面小編就為大家?guī)硪黄狫ava語言----三種循環(huán)語句的區(qū)別介紹。小編舉得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-07-07