当前位置: 首页 > news >正文

myabtis流式查询

1、流式查询简介

流式处理在大数据方面应用比较广泛。随着数据的爆发式增长,流式处理的方式也被应用到日常的工具中,如JDK的对于集合处理的Stream流、Redis5.0新增的数据结构Stream专门来处理消息等。

流式查询指的是查询成功后不是返回一个集合而是返回一个迭代器,应用每次从迭代器取一条查询结果。流式查询的好处是能够降低内存使用。

今天要分享的是Mybaits的流式查询。Mybatis流式查询通过使用游标一次处理一条数据的方式,减少了内存的占用,从而提高了大数据量查询的效率。

2、Mybaits流式查询

Mybaits3.4.0 版本增加了流式查询也就是游标Cursor。更新日志传动门,Issues · mybatis/mybatis-3 · GitHub

2.1 游标简介

游标的使用和List一样,只不过返回的结果不同。

游标继承CloseableIterable接口,所以游标是可关闭、可遍历的。包含三个方法:

  • isOpen 游标的开关是否打开

  • isConsumed 通过游标是否将拉取的数据消费完,也就是是否将数据全部取完。

  • getCurrentIndex 获取当前数据的位置,位置是从0开始的。

2.2 游标的使用

定义简单的查询方法,这里使用注解@Select的方式代替Xml,方便测试。

@Select("select * from logan_log.logan_login")
Cursor<LoganLogin> testCursorQuery();

编写测试类。因为游标是可关闭的,所以使用完之后要想流一样关闭掉。这里采用try-resource 的方式简化流的关闭。

@Test
void testCursorSql() {try (Cursor<LoganLogin> cursor = loganLoginMapper.testCursorQuery()) {cursor.forEach((ll) -> {System.out.println("ll:" + JSON.toJSONString(ll));System.out.println("ll cursor:" + cursor.getCurrentIndex());});} catch (IOException e) {throw new RuntimeException(e);}
}

处理结果,报错了。。。

原因分析:

  • A Cursor is already closed. 还没有处理数据,查询完数据之后游标被关闭了。

  • 由于Mybatis帮我们做了自动事务的提交。查询完毕之后就会提交事务关闭连接,游标自然也被关闭了,就会出现这样的问题。游标需要占用数据库的连接,然后逐条的将数据返回的。

解决方案:

  • 将整个方法放在一个事务里面,处理完数据之后在提交事务。比较暴力的解决方案就是使用声明式事务@Transactional。大事务的处理可能会影响业务的并发。

  • 采用小颗粒度的编程式事务TransactionTemplate,只针对流式查询的结果包装到一个事务里面即可。

  • 也可以采用手动提交事务,使用SqlSessionFactory手动建立连接和关闭。

编程式事务解决问题可能更方便一些,所以采用编程式事务的方法解决。

@Test
void testCursorSql2() {transactionTemplate.execute(new TransactionCallbackWithoutResult() {@Overrideprotected void doInTransactionWithoutResult(TransactionStatus status) {System.out.println("TransactionStatus1:" + status.hasSavepoint());try (Cursor<LoganLogin> cursor = loganLoginMapper.testCursorQuery()) {cursor.forEach((ll) -> {System.out.println("ll:" + JSON.toJSONString(ll));System.out.println("ll cursor:" + cursor.getCurrentIndex());});System.out.println("TransactionStatus2:" + status.hasSavepoint());} catch (IOException e) {throw new RuntimeException(e);}}});
}

结果正常打印

2.3 游标查询的升级

游标的使用总会便随着事务,对于开发者来说成了黄金搭档。能不能将其封装成一个方法来方便开发者调用呢,还真有。就是使用ResultHandler参数。

有人就提出了对应的issues,同时也在mybatis-3.4.6得到了支持。

2.3.1 ResultHandler参数说明

ResultHandler 作为参数参数传递,返回值为Void。xml的配置需要指定ResultType

查询到的结果,也是封装在ResultHandler 里面的ResultContext中。

  • T getResultObject() 返回的数据结果

  • int getResultCount() 返回当前结果的记录数据。

  • boolean isStopped() 是否停止拉取数据

  • void stop() 中断数据拉取

2.3.2 ResultHandler的使用

ResultHandler 的使用,官方文档中已经给出使用案例。我们来测试一下。

先定义一下方法。同样采用注解的方式替代xml

@ResultType(LoganLogin.class)
@Select("select * from logan_log.logan_login")
void testStreamQuery(ResultHandler<LoganLogin> handler);

其中ResultType 必须要指定,否则就会报错。

测试案例

@Test
void testStreamSql() {loganLoginMapper.testStreamQuery(resultContext -> {System.out.println("handleResult:" + JSON.toJSONString(resultContext.getResultObject()));System.out.println("ResultCount:" + resultContext.getResultCount());System.out.println("isStop:" + resultContext.isStopped());System.out.println("---------------------------------------");});
}

测试结果

2.4 fetchSize 的讨论

很多技术博客中都强调,fetchSize 可以控制每次拉取的数量。

但是笔者配置,测试之后发现并没有什么效果。在使用流式查询时,官方文档中也没有说明必须要配置。

元芳,你怎么看???

3、流式查询在Mybatis-Plus中的使用

mybatis中已经支持了流式查询,那么好用的MP怎么会不支持。MP在3.5.4中也得到了支持。

具体的方法如下:

/*** 根据 entity 条件,查询全部记录** @param queryWrapper  实体对象封装操作类(可以为 null)* @param resultHandler 结果处理器 {@link ResultHandler}* @since 3.5.4*/
void selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper, ResultHandler<T> resultHandler);/*** 根据 entity 条件,查询全部记录(并翻页)* @param page          分页查询条件* @param queryWrapper  实体对象封装操作类(可以为 null)* @param resultHandler 结果处理器 {@link ResultHandler}* @since 3.5.4*/
void selectList(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper, ResultHandler<T> resultHandler);
/*** 根据 Wrapper 条件,查询全部记录** @param queryWrapper  实体对象封装操作类* @param resultHandler 结果处理器 {@link ResultHandler}* @since 3.5.4*/
void selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper, ResultHandler<Map<String, Object>> resultHandler);
/*** 根据 Wrapper 条件,查询全部记录(并翻页)** @param page          分页查询条件* @param queryWrapper  实体对象封装操作类* @param resultHandler 结果处理器 {@link ResultHandler}* @since 3.5.4*/
void selectMaps(IPage<? extends Map<String, Object>> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper, ResultHandler<Map<String, Object>> resultHandler);
/*** 根据 Wrapper 条件,查询全部记录* <p>注意: 只返回第一个字段的值</p>** @param queryWrapper  实体对象封装操作类(可以为 null)* @param resultHandler 结果处理器 {@link ResultHandler}* @since 3.5.4*/
<E> void selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper, ResultHandler<E> resultHandler);

就拿最典型的selectList来测试。

没有分页的查询。其中Wrapper主要是查询的Sql 的条件拼接,也可以是空。ResultHandler就是我们的流式返回了。

@Test
void testStreamPlus() {loganLoginMapper.selectList(Wrappers.emptyWrapper(), resultContext->{System.out.println("handleResult:" + JSON.toJSONString(resultContext.getResultObject()));System.out.println("ResultCount:" + resultContext.getResultCount());System.out.println("isStop:" + resultContext.isStopped());System.out.println("---------------------------------------");});
}

测试结果

有分页的查询和无分页方法是重载关系,增加了分页参数Page。其中Page只是限定了拉取数据的总条数,但是并不会自动封装到Page对象中。主要使用了, resultContextstop的方法。

@Test
void testStreamPage() {Page<LoganLogin> page = new Page<>(1, 2);loganLoginMapper.selectList(page, Wrappers.emptyWrapper(), resultContext->{System.out.println("当前处理第" + resultContext.getResultCount() + "条记录.");System.out.println("handleResult:" + JSON.toJSONString(resultContext.getResultObject()));System.out.println("isStop:" + resultContext.isStopped());System.out.println("---------------------------------------");});System.out.println(JSON.toJSONString(page.getRecords()));
}

测试结果

相关文章:

myabtis流式查询

1、流式查询简介 流式处理在大数据方面应用比较广泛。随着数据的爆发式增长&#xff0c;流式处理的方式也被应用到日常的工具中&#xff0c;如JDK的对于集合处理的Stream流、Redis5.0新增的数据结构Stream专门来处理消息等。 流式查询指的是查询成功后不是返回一个集合而是返回…...

K8S的pod创建过程

创建流程图 用户发起请求创建deployment&#xff1b;apiserver收到创建资源的请求&#xff0c;apiserver对客户端操作进行身份认证&#xff0c;认证完成后接受该请求&#xff0c;并把相关的信息保存到etcd中&#xff0c;然后返回确认信息给客户端&#xff1b;apiserver向etcd…...

java修仙传之海岛奇遇

昨日开会&#xff0c; 商量了一下接口返回数据&#xff0c; 要求统一&#xff0c; 之前也同意&#xff0c;直接抛异常&#xff0c; 现在觉得之前那个异常不好&#xff0c; 看着不美观&#xff0c;对客户不友好 要求重新做。 大概要求如下&#xff1a; 要求1&#xff1a;范…...

电子商务平台对接电商供应链,不得不说的开放平台电商API接口

B2B电商开放平台的设计需要从以下几面去思考&#xff1a; 开放平台API接口的设计&#xff0c;主要是从功能需求的角度&#xff0c;设计满足业务需求的接口及对应的字段&#xff1b; 平台与商家之间信息的对接&#xff0c;对接的方法有哪些&#xff1f;对接过程中需要可能会遇到…...

【JAVA学习笔记】 57 - 本章作业

项目代码 https://github.com/yinhai1114/Java_Learning_Code/tree/main/IDEA_Chapter14/src/com/yinhai/homework 1. (1)封装个新闻类&#xff0c;包含标题和内容属性&#xff0c;提供get, set方法&#xff0c; 重写toString方法&#xff0c;打印对象时只打印标题; (2)只提供…...

【题解】[GenshinOI Round 3] P9816 少项式复合幂

题目链接 分析 首先这题给了很大的提示信息 注意 m 和 p 的范围 , 很自然的想到可以先把所有可能的 f ( x ) f(x) f(x) 算出来. 思维误区 有些人在算完 f ( x ) f(x) f(x) 之后可能就会去思考找环的问题&#xff0c;然后一些码力弱的大佬就会祭掉. 在经过仔细的观察之后…...

手写数字识别--神经网络实验

实验源码自取&#xff1a; 神经网络实验报告源码.zip - 蓝奏云 上深度学习的课程&#xff0c;老师布置了一个经典的实验报告&#xff0c;我做了好久才搞懂&#xff0c;所以把实验报告放到CSDN保存&#xff0c;自己忘了方便查阅&#xff0c;也为其他人提供借鉴 由于本人是小白…...

双11消费遇冷?如何让消费回归心智原点

近一年来&#xff0c;小红书话题「重新养育自己」引热议。直面成长缺憾&#xff0c;不少人探寻解决方案&#xff0c;即像对待新生命般&#xff0c;不论是衣食住行还是心灵&#xff0c;重新关照自己。 借此&#xff0c;本期千瓜将锁定小红书热门话题背后的消费观转变&#xff0…...

一分钟了解:什么是Image Matting?

1. 基本概念 Image Matting是图像处理领域的一个基本任务&#xff0c;意为“图像背景抠出”或者“抠图”。这项任务在图像处理、影视制作领域广泛应用。比如&#xff0c;拍电影时常用的扣绿&#xff0c;就是演员在绿幕前面表演&#xff0c;后期再把人物抠出来放到一个新的背景…...

微信小程序 跳转客服页面

前言 小程序 用户反馈 没有页面设计 可以直接跳转小程序指定客服页面 <button class"contactBtn"open-type"contact" contact"handleContact" session-from"sessionFrom">...

10个简单增删改查的免费Spring Boot源代码项目

此页面包含用于学习目的的免费 Spring boot 项目列表。每个 Spring boot 项目的源代码都托管在 GitHub 存储库上&#xff0c;因此您可以免费下载或克隆源代码并亲身体验 Spring boot 框架。 1.员工管理应用程序&#xff08;ReactJS Spring Boot CRUD全栈应用程序&#xff09; …...

mysql数据表设计

命名 mysql表名的命名规范为表名可以用 t_ 、tb_的前缀&#xff0c;或者是业务模块前缀。比如t_order。 有些项目也会使用 tt_、tm_、 ts_ 等前缀&#xff0c;根据项目的习惯命名就好了。 主键&#xff1a; AUTO_INCREMENT 表示自增&#xff0c;UNSIGNED 表示无符号&#xf…...

pytorch复现4_Resnet

ResNet在《Deep Residual Learning for Image Recognition》论文中提出&#xff0c;是在CVPR 2016发表的一种影响深远的网络模型&#xff0c;由何凯明大神团队提出来&#xff0c;在ImageNet的分类比赛上将网络深度直接提高到了152层&#xff0c;前一年夺冠的VGG只有19层。Image…...

【数据库】形式化关系查询语言(一):关系代数Relational Algebra:基本运算、附加关系代数、扩展的关系代数

目录 一、关系代数Relational Algebra 1. 基本运算 a. 选择运算&#xff08;Select Operation&#xff09; b. 投影运算&#xff08;Project Operation&#xff09; 组合 c. 并运算&#xff08;Union Operation&#xff09; d. 集合差运算&#xff08;Set Difference Op…...

【计算机网络】计算机网络和因特网

一.基本术语介绍 端系统通过通信链路&#xff08;communication link&#xff09;和分组交换机&#xff08;packet switch&#xff09;连接到一起&#xff0c;连接这些端系统和分组交换机的物理媒体包括&#xff1a;同轴电缆&#xff0c;铜线&#xff0c;光纤和无线电频谱。而…...

JAVA面经整理(9)

一)什么是Spring&#xff1f;它有什么优点? spring是一款顶级的开源框架&#xff0c;他是包含了众多工具方法的IOC容器&#xff0c;Spring中包含了很多模块&#xff0c;比如说Spring-core&#xff0c;Spring-context&#xff0c;Spring-aop&#xff0c;Spring-web&#xff0c;…...

IPD(集成产品开发)模式下的产品研发流程

IPD&#xff08;集成产品开发&#xff09;涵盖了产品从创意提出到研发、生产、运营等&#xff0c;包含了产品开发到营销运营的整个过程。围绕产品&#xff08;或项目&#xff09;生命周期的过程的管理模式&#xff0c;是一套生产流程&#xff0c;更是时下国际先进的管理体系。I…...

Flutter GetX的使用

比较强大的状态管理框架 引入库&#xff1a; dependencies:get: ^4.6.6一.实现一个简单的demo 实现一个计数器功能 代码如下&#xff1a; import package:flutter/material.dart; import package:get/get.dart;void main() > runApp(const GetMaterialApp(home: Home()…...

【Amazon】AWS实战 | 快速发布安全传输的静态页面

文章目录 一、实验架构图二、实验涉及的AWS服务三、实验操作步骤1. 创建S3存储桶&#xff0c;存放网站网页2. 使用ACM建立域名证书3. 设置Cloudfront&#xff0c;连接S3存储桶✴️4. 设置Route53&#xff0c;解析域名服务5. 通过CLI工具上传网页更新内容【可选】 四、实验总结 …...

前后端登录的密码加密和解密

在一个典型的前后端应用中&#xff0c;前端对密码进行加密后传给后端&#xff0c;后端再进行解密或验证。这通常涉及前端加密、后端解密或验证的相互配合。下面是一个基本的流程&#xff1a; 前端加密&#xff1a; 前端可以使用各种加密库或算法对密码进行加密。常见的是使用哈…...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...

<6>-MySQL表的增删查改

目录 一&#xff0c;create&#xff08;创建表&#xff09; 二&#xff0c;retrieve&#xff08;查询表&#xff09; 1&#xff0c;select列 2&#xff0c;where条件 三&#xff0c;update&#xff08;更新表&#xff09; 四&#xff0c;delete&#xff08;删除表&#xf…...

【解密LSTM、GRU如何解决传统RNN梯度消失问题】

解密LSTM与GRU&#xff1a;如何让RNN变得更聪明&#xff1f; 在深度学习的世界里&#xff0c;循环神经网络&#xff08;RNN&#xff09;以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而&#xff0c;传统RNN存在的一个严重问题——梯度消失&#…...

跨链模式:多链互操作架构与性能扩展方案

跨链模式&#xff1a;多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈&#xff1a;模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展&#xff08;H2Cross架构&#xff09;&#xff1a; 适配层&#xf…...

【HTTP三个基础问题】

面试官您好&#xff01;HTTP是超文本传输协议&#xff0c;是互联网上客户端和服务器之间传输超文本数据&#xff08;比如文字、图片、音频、视频等&#xff09;的核心协议&#xff0c;当前互联网应用最广泛的版本是HTTP1.1&#xff0c;它基于经典的C/S模型&#xff0c;也就是客…...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心

当仓库学会“思考”&#xff0c;物流的终极形态正在诞生 想象这样的场景&#xff1a; 凌晨3点&#xff0c;某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径&#xff1b;AI视觉系统在0.1秒内扫描包裹信息&#xff1b;数字孪生平台正模拟次日峰值流量压力…...

python报错No module named ‘tensorflow.keras‘

是由于不同版本的tensorflow下的keras所在的路径不同&#xff0c;结合所安装的tensorflow的目录结构修改from语句即可。 原语句&#xff1a; from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后&#xff1a; from tensorflow.python.keras.lay…...

Go 语言并发编程基础:无缓冲与有缓冲通道

在上一章节中&#xff0c;我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道&#xff0c;它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好&#xff0…...

抽象类和接口(全)

一、抽象类 1.概念&#xff1a;如果⼀个类中没有包含⾜够的信息来描绘⼀个具体的对象&#xff0c;这样的类就是抽象类。 像是没有实际⼯作的⽅法,我们可以把它设计成⼀个抽象⽅法&#xff0c;包含抽象⽅法的类我们称为抽象类。 2.语法 在Java中&#xff0c;⼀个类如果被 abs…...

DBLP数据库是什么?

DBLP&#xff08;Digital Bibliography & Library Project&#xff09;Computer Science Bibliography是全球著名的计算机科学出版物的开放书目数据库。DBLP所收录的期刊和会议论文质量较高&#xff0c;数据库文献更新速度很快&#xff0c;很好地反映了国际计算机科学学术研…...