流式查询:逐条返回

SpringBoot流式返回完整指南:从入门到精通 SpringBoot流式返回技术指南摘要 本文全面介绍SpringBoot中流式返回的实现方法与应用场景。流式返回(Streaming Response)支持服务器持续向客户端发送数据,适用于实时数据、大文件处理和消息推送等场景。SpringBoot通过WebFlux和Reactive Streams提供强大支持,核心类包括Flux、Mono和ServerSentEvent等。文章详细展示了文本流、JSON数据流、SSE推送等基础实现,以及数据库查询流、大文件下载和消息队列集成等高级应用。关键优势包括实时性 阅读详情

MyBatis Cursor + Reactor Flux.create

        MyBatis 提供了 Cursor 接口,它本质上是对 JDBC ResultSet 的一个包装。当使用 Cursor 时,MyBatis 不会一次性将所有结果加载到内存中,而是逐行从数据库读取。我们可以将这个逐行的、阻塞的迭代过程,转换成一个非阻塞的、异步的 Flux 数据流。

        数据流如下:MySQL -> JDBC ResultSet (流式) -> MyBatis Cursor -> (在专用线程中迭代) -> Flux.create -> Spring WebFlux Controller -> Client

实现步骤与代码示例

第一步:MyBatis Mapper 层配置游标查询

在你的 Mapper 接口中,定义一个返回 Cursor 的方法。

import org.apache.ibatis.cursor.Cursor;

@Mapper
public interface HugeDataMapper {
    // 方法返回类型必须是 Cursor
    Cursor<YourDataModel> streamAllData();
}

对应的 XML 映射文件(如果使用XML):

<select id="streamAllData" resultType="YourDataModel">
    SELECT * FROM your_huge_table
    <!-- 可以添加 WHERE 条件等 -->
</select>

关键点: 仅仅是定义返回 Cursor,MyBatis 就会使用流式方式执行查询。

第二步:Service 层封装为 Flux

        这是最关键的一步。我们需要在一个专门的、有边界的线程池(Schedulers.boundedElastic())中执行这个阻塞的游标遍历操作,并将每一行数据通过 Flux.create 的 sink 发射出去。

import reactor.core.publisher.Flux;
import reactor.core.scheduler.Schedulers;
import org.apache.ibatis.cursor.Cursor;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class StreamService {

    private final HugeDataMapper hugeDataMapper; // 你的 MyBatis Mapper

    public Flux<YourDataModel> streamHugeData() {
        return Flux.create(sink -> {
            // 这段代码将在弹性线程池中执行,不会阻塞WebFlux的事件循环线程
            try (Cursor<YourDataModel> cursor = hugeDataMapper.streamAllData()) {
                cursor.forEach(sink::next); // 逐行遍历,并通过sink发射数据
                sink.complete(); // 遍历完成,发出完成信号
            } catch (Exception e) {
                sink.error(e); // 发生异常,发出错误信号
            }
        }).subscribeOn(Schedulers.boundedElastic()); // 指定上述操作所在的线程池
    }
}

代码解释:
        (1) Flux.create: 创建一个 Flux,我们可以完全控制如何向其中发射数据。
        (2) subscribeOn(Schedulers.boundedElastic()): 这是至关重要的一步。它将整个阻塞的游标遍历操作(包括数据库查询)转移到一个专门的、大小受限的弹性线程池中执行。这保护了 WebFlux 用于处理高并发请求的有限的事件循环线程(EventLoop Thread),防止它们被阻塞操作拖垮。在
        (3) create 的回调中:
        使用 forEach 逐行遍历,每拿到一行数据,就调用 sink.next(data) 将其发射出去。
        遍历完成后调用 sink.complete()。
        用 try-with-resources 语句确保 Cursor 和底层的 ResultSet、Connection 会被正确关闭。

第三步:Controller 层暴露流式端点

在 Controller 中,注入 Service 并返回这个 Flux。

import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequiredArgsConstructor
public class StreamingController {

    private final StreamService streamService;

    @GetMapping(value = "/stream/data", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<YourDataModel> streamData() {
        return streamService.streamHugeData();
    }
}

关键点:

        (1) produces = MediaType.TEXT_EVENT_STREAM_VALUE: 这声明了该端点使用 Server-Sent Events (SSE) 协议进行响应。这是最常用的流式传输协议,前端可以直接用 EventSource API 来消费。

        (2) 你也可以使用 MediaType.APPLICATION_NDJSON_VALUE,它会以换行符分隔的 JSON 格式返回数据。

第四步:配置

1. MySQL JDBC 连接参数

        为了确保 MySQL JDBC 驱动真正使用流式传输,必须在数据库连接 URL 中配置以下参数:properties

# application.properties

spring.datasource.url=jdbc:mysql://your-host:3306/your-db?
    useCursorFetch=true& # 启用游标抓取
    defaultFetchSize=-2147483648&# 设置默认抓取大小为 Integer.MIN_VALUE,这是驱动层流式传输的关键
    characterEncoding=UTF-8&
    serverTimezone=Asia/Shanghai

defaultFetchSize=-2147483648 是驱动识别为“流式模式”的魔法值。useCursorFetch=true 与之配合使用。

2. 连接池配置 (重要!)

        必须确保连接池不会干扰流式查询。 常见的连接池(如 HikariCP)会在连接归还时关闭任何打开的 ResultSet,这会立即中断你的流。

解决方案:使用 Spring 事务管理, 在 @Transactional 注解的方法中执行游标查询,这样可以保证在整个流式读取完成之前,连接不会被归还。你可以将 @Transactional 注解加在 Mapper 方法上或 Service 方法上。

@Service
public class StreamService {
    ...

    @Transactional // 添加事务注解,保持连接直到整个流处理完毕
    public Flux<YourDataModel> streamHugeData() {
        return Flux.create(sink -> {
            try (Cursor<YourDataModel> cursor = hugeDataMapper.streamAllData()) {
                cursor.forEach(sink::next);
                sink.complete();
            } catch (Exception e) {
                sink.error(e);
            }
        }).subscribeOn(Schedulers.boundedElastic());
    }
}

易康eCognition9.0分类|规则集和机器学习的方法的面向对象的多尺度分割分类 基于易康eCognition9.0软件的规则集和机器学习的方法的面向对象的多尺度分割分类 阅读详情

相关推荐

DCA决策曲线的解读和代码实现

0.决策曲线 决策曲线分析法(Decision Curve Analysis,DCA)是个与ROC曲线相提并论的相对比较新的模型评价方法。 关于它的原理,长篇大论的医学统计学知识解读实在不是我的强项,放上两个链接偷偷懒: https://www.plob.org/article/12455.html https://www.iikx.com/news/statistics/1622.html 如果想看文章,这篇里的fig7就是:https://www.ncbi.nlm.nih.gov/pmc/artic

weixin_42960896的博客 1万+

nginx 子目录代理的Flux缓存问题,用二级域名访问 flux 接口可以正常流式输出(chunked),但通过 nginx 子目录访问时却一次性返回全部内容,没有流式效果。

摘要:Nginx反向代理默认会缓冲后端响应,导致即使后端开启chunked传输也无法实时流式输出。解决方案是在location配置中关闭缓冲功能,关键配置包括:设置proxy_buffering和proxy_cache为off,并开启chunked_transfer_encoding。这样就能实现真正的流式传输,特别适用于需要实时响应的服务代理场景。

g470641382的博客 413

华大HC32F460从零到200MHz:手把手教你配置时钟系统(附避坑指南)

本文详细解析了华大HC32F460 MCU的时钟系统配置,从启动过程、时钟树分析到实战配置200MHz系统时钟。文章手把手指导开发者如何正确配置外部晶振、MPLL锁相环及总线分频,并提供了硬件检查、代码解读及常见问题排查的避坑指南,帮助用户从零构建稳定可靠的高性能时钟环境。

net55的博客 296

使用IDEA开发FLUX小红书V2模型Java接口的完整教程

本文介绍了如何在星图GPU平台上自动化部署FLUX.小红书极致真实 V2 图像生成工具镜像,快速构建Java后端调用能力。通过标准化API集成,开发者可高效生成高真实感、小红书风格的日常场景图片,适用于内容创作、电商配图及社交媒体素材生产等典型场景。

weixin_35752233的博客 282

语义通信实战:跳过“比特”保“语义”,手把手构建轻量级图像压缩重建网络(基于PyTorch)

本文详细介绍了基于PyTorch的轻量级语义通信系统LICRnet的实现,专注于图像压缩重建中的语义信息保留。通过深度可分离卷积、可变窗口多尺度注意力等创新技术,显著降低计算量并提升性能,特别适用于无人机巡检、远程医疗等物联网场景。文章包含完整的代码实现、训练策略及部署优化方案。

weixin_27697385的博客 221

mysql流式查询mybatis_MyBatis 如何实现流式查询

基本概念流式查询指的是查询成功后不是返回一个集合而是返回一个迭代器,应用每次从迭代器取一条查询结果。流式查询的好处是能够降低内存使用。如果没有流式查询,我们想要从数据库取 1000 万条记录而又没有足够的内存时,就不得不分页查询,而分页查询效率取决于表设计,如果设计的不好,就无法执行高效的分页查询。因此流式查询是一个数据库访问框架必须具备的功能。流式查询的过程当中,数据库连接是保持打开状态的,因此...

weixin_39610774的博客 385

百度慧眼人口位置数据:从原理到实战的GIS处理全流程

本文详细解析百度慧眼人口位置数据的处理全流程,从基本原理到实战应用。通过空间网格划分、终端数量统计等技术手段,百度慧眼数据能准确反映人群分布特征。文章涵盖坐标系转换、核密度分析、热力图制作等GIS处理技巧,并分享商业选址、城市规划等典型业务场景的解决方案,帮助读者高效利用这一数据资源。

weixin_30872157的博客 534

java 数据库 流式查询_MyBatis如何实现流式查询的示例代码

基本概念流式查询指的是查询成功后不是返回一个集合而是返回一个迭代器,应用每次从迭代器取一条查询结果。流式查询的好处是能够降低内存使用。如果没有流式查询,我们想要从数据库取 1000 万条记录而又没有足够的内存时,就不得不分页查询,而分页查询效率取决于表设计,如果设计的不好,就无法执行高效的分页查询。因此流式查询是一个数据库访问框架必须具备的功能。流式查询的过程当中,数据库连接是保持打开状态的,因此...

weixin_34524593的博客 586

网络设备心跳线带宽高导致虚拟化平台不稳定的问题处理

本文记录了网络设备心跳线带宽高导致虚拟化平台不稳定的问题处理一例。

forestqq的博客 2228

【自适应滤波】自适应UKF,基于新息自适应调节Q和R,场景为雷达跟踪与滤波、MATLAB实现

本文提出了一种基于新息协方差匹配的自适应UKF(CM-AUKF)算法,用于解决噪声统计未知或时变场景下的目标跟踪问题。通过实时调整过程噪声协方差Q和观测噪声协方差R,CM-AUKF显著提升了跟踪精度和稳定性。仿真结果表明,相比传统UKF,CM-AUKF在位置和速度估计误差上分别降低了约50%和30%,且无需人工调参。该算法适用于无人机导航、雷达跟踪等动态环境,MATLAB代码可直接运行复现结果。自适应曲线显示算法能有效收敛到真实噪声参数,验证了其自适应能力。

985工科博士毕业,专攻定位、导航和滤波等算法研究。从业10年,主要使用MATLAB 329

mybatis 取查询值_MyBatis 如何实现流式查询?

基本概念流式查询指的是查询成功后不是返回一个集合而是返回一个迭代器,应用每次从迭代器取一条查询结果。流式查询的好处是能够降低内存使用。如果没有流式查询,我们想要从数据库取 1000 万条记录而又没有足够的内存时,就不得不分页查询,而分页查询效率取决于表设计,如果设计的不好,就无法执行高效的分页查询。因此流式查询是一个数据库访问框架必须具备的功能。流式查询的过程当中,数据库连接是保持打开状态的,因此...

weixin_36236774的博客 311

第55篇:数据隐私保护技术盘点——差分隐私、同态加密与它们的坑(踩坑总结)

数据隐私保护是AI工程化中必须严肃对待的课题。差分隐私和同态加密是两把利器,但也都是“重武器”,使用不当反而会伤及自身。差分隐私像“模糊处理”,通过加噪来保证统计安全性,要小心管理隐私预算和效用权衡。同态加密像“保险箱里打算盘”,保证了计算的精确性,但必须承受巨大的性能和工程复杂度代价。我的建议是:从小规模实验开始,先用DP-SGD在MNIST/CIFAR-10等标准数据集上感受噪声与精度的关系;再用TenSEAL等易用的库尝试一个加密逻辑回归,体会密文膨胀和速度延迟。

ai_blue_pm的博客 281

Mybatis流式查询

版权声明:本文为优快云博主「污鸦嘴」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。处理的需求,因数据量过大不能一次性将结果集装入客户端内存,就可以考虑使用流式查询或者分页查询, 本文仅讨论流式查询.规则 类似于oracle的fetchsize缓冲区。方式三: TransactionTemplate。方式四: @Transactional 注解。方式二: SqlSession 方式。方式一: 基于mybatis的。基于Cursor构建的方式。话不多说 直接上代码。

很多时候犯错都是在不知情的情况下发生的 7949

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

Mybatis之批处理流式查询

流式查询指的是查询成功后不是返回一个集合而是返回一个迭代器,应用每次从迭代器取一条查询结果。流式查询的好处是能够降低内存使用。如果没有流式查询,我们想要从数据库取1000 万条记录而又没有足够的内存时,就不得不分页查询,而分页查询效率取决于表设计,如果设计的不好,就无法执行高效的分页查询。因此流式查询是一个数据库访问框架必须具备的功能。MyBatis中使用流式查询避免数据量过大导致OOM执行一个流式查询后,数据库访问框架就不负责关闭数据库连接了,需要应用在取完数据后自己关闭。

上善若泪 3929

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

mybatis流式查询

数据库框架mybatis的流式查询知识点前言MyBatis 流式查询接口但构建 Cursor 的过程不简单方案一:SqlSessionFactory方案二:TransactionTemplate方案三:@Transactional 注解实战使用pom文件中的配置mapper.xml文件配置自定义ResultHandler来分批处理结果集ServiceImpl类中的使用总结深入了解MySQL的流式查询机制为什么要用流式查询?1、oracle等商业数据库的fetchsize2、流式查询与MySQL fetchs

qq_41134142的博客 1万+

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

Mybatis 流式查询

Mybatis 流式查询 简介:流式查询指的是数据库查询成功后,返回一个迭代器,而不是返回一个集合,每次从迭代器取一条查询结果放到缓存器中,当缓存器满了之后,放到结果集中,清空缓存,按游标位置继续读取数据。流式查询的好处是能够降低内存使用,防止java内存溢出(OOM,全称OUT OF MEMORY)。 原理 和StringBuffer的原理相似,Mybatis 流式查询是逐条将读取的数据放到resultset结果集中 流程 client发送select查询请求给Server Server根据条件筛选

棉花糖的博客 3680

MyBatis流式查询

MyBatis流式查询

爱笑的boy的博客 1万+

MySQL 普通查询、流式查询、游标查询以及使用 mybatis 如何实现

MySQL 普通查询、流式查询、游标查询以及使用 mybatis 如何实现

赵丙双的博客 7843

MyBatis 流式查询

上面的代码中,1 处我们创建了一个 TransactionTemplate 对象(此处 transactionManager 是怎么来的不用多解释,本文假设读者对 Spring 数据库事务的使用比较熟悉了),2 处执行数据库事务,而数据库事务的内容则是调用 Mapper 对象的流式查询。流式查询的过程当中,数据库连接是保持打开状态的,因此要注意的是:执行一个流式查询后,数据库访问框架就不负责关闭数据库连接了,需要应用在取完数据后自己关闭。所以,解决这个问题的思路不复杂,保持数据库连接打开即可。

Angus博客 1715

Mybatis流式查询之ResultHanlde

0.前言 如果目标数据量过大,又需要全量查询,不能分页的情况,例如导出excel,就需要流式查询 1. 实例 1.1.Mybaits的jar包引入 注:idea必须配置build,否则扫描不到src下的xml文件 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSche

relife 7741

MyBatis 如何实现流式查询

目录 基本概念 MyBatis 流式查询接口 但构建 Cursor 的过程不简单 方案一:SqlSessionFactory 方案二:TransactionTemplate 方案三:@Transactional 注解 基本概念 流式查询指的是查询成功后不是返回一个集合而是返回一个迭代器,应用每次从迭代器取一条查询结果。流式查询的好处是能够降低内存使用。 如果没有流式查询,我们想要从数据库取 1000 万条记录而又没有足够的内存时,就不得不分页查询,而分页查询效率取决于表设计,如果设计的不好

琦彦 5622

基于mybatis实现流式查询

什么是流式查询? 流式查询指的是查询成功后不是返回一个集合而是返回一个迭代器,应用每次从迭代器取一条查询结果。流式查询的好处是能够降低内存使用。 如果没有流式查询,我们想要从数据库取 1000 万条记录而又没有足够的内存时,就不得不分页查询,而分页查询效率取决于表设计,如果设计的不好,就无法执行高效的分页查询。因此流式查询是一个数据库访问框架必须具备的功能。 ⚠️流式查询的过程当中,数据库连接是保持打开状态的,因此要注意的是:执行一个流式查询后,数据库访问框架就不负责关闭数据库连接了,需要应用.

JAVA拾贝 6737

深入了解MySQL的流式查询机制

引言 为什么要用流式查询? a) 如果有一个很大的查询结果需要遍历处理,又不想一次性将结果集装入客户端内存,就可以考虑使用流式查询; b)分库分表场景下,单个表的查询结果集虽然不大,但如果某个查询跨了多个库多个表,又要做结果集的合并、排序等动作,依然有可能撑爆内存;详细研究了sharding-sphere的代码不难发现,除了group by与order by字段不一样之外,其他的场景都非常适...

nym232的博客 1万+
上一篇: Java泛型(补档)
下一篇: MySQL深分页的处理方案
快乐吃手手  :  )
博客等级 码龄6年 119粉丝 25原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值