0

0

Spring Data JPA 流查询方法

DDD

DDD

发布时间:2024-11-17 16:24:20

|

467人浏览过

|

来源于dev.to

转载

spring data jpa 流查询方法

介绍

传统上,获取大量数据可能会导致内存资源紧张,因为它通常涉及将整个结果集加载到内存中。

=> 流查询方法通过提供一种使用 java 8 streams 增量处理数据的方法来提供解决方案。这可确保任何时候只有一部分数据保存在内存中,增强性能和可扩展性

在这篇博文中,我们将深入研究流查询方法在 spring data jpa 中的工作原理,探索它们的用例,并演示它们的实现。

对于本指南,我们使用:

    ide:intellij idea(推荐用于 spring 应用程序)或 eclipse
  • java 版本:17
  • spring data jpa 版本:2.7.x 或更高版本(与 spring boot 3.x 兼容)
  • 
        org.springframework.boot
        spring-boot-starter-data-jpa
    
    
注意:有关更详细的示例,请访问我的 github 存储库

1.什么是流查询方式?

spring data jpa 中的流查询方法允许我们以 stream 的形式返回查询结果,而不是 list 或其他集合类型。这种方法有几个好处:

  • 高效的资源管理:增量处理数据,减少内存开销。

  • 延迟处理:按需获取和处理结果,非常适合分页或批处理等场景。

  • 与函数式编程集成:流符合 java 的函数式编程特性,支持过滤、映射和收集等操作。

    唱鸭
    唱鸭

    音乐创作全流程的AI自动作曲工具,集 AI 辅助作词、AI 自动作曲、编曲、混音于一体

    下载
2.如何使用流查询方法?

=> 假设我们正在开发一个电子商务应用程序并希望:

    检索在特定日期之后下订单的所有客户。
  • 过滤总金额高于特定提供金额的订单。
  • 按过去 6 个月内的订单总价值对客户进行分组。
  • 返回数据作为客户名称及其总订单价值的摘要。

实体

    客户:代表客户。
  • @setter
    @getter
    @entity
    @entity(name = "tbl_customer")
    public class customer {
        @id
        @generatedvalue(strategy = generationtype.identity)
        private long id;
    
        private string name;
        private string email;
    
        @onetomany(mappedby = "customer", cascade = cascadetype.all, fetch = fetchtype.lazy)
        private list orders;
    }
    
    订单:代表客户下的订单。
  • @setter
    @getter
    @entity(name = "tbl_order")
    public class order {
        @id
        @generatedvalue(strategy = generationtype.identity)
        private long id;
    
        private double amount;
        private localdatetime orderdate;
    
        @manytoone
        @joincolumn(name = "customer_id")
        private customer customer;
    }
    

存储库

    customerrepository 用于选择客户及其在特定日期之后下的相关订单。我们使用 stream 而不是 list 来处理查询结果。
  • public interface customerrepository extends jparepository {
        @query("""
                    select c from tbl_customer c join fetch c.orders o where o.orderdate >= :startdate
                """)
        @queryhints(
                @queryhint(name = availablehints.hint_fetch_size, value = "25")
        )
        stream findcustomerwithorders(@param("startdate") localdatetime startdate);
    }
    
注意:

  • join fetch 确保订单被急切加载。

  • @queryhints 用于向 jpa(例如 hibernate)提供额外提示以优化查询执行。

=> 例如,当我的查询返回 100 条记录时:

    前 25 条记录由应用程序获取并处理。
  • 处理完这些后,将获取接下来的 25 条记录,依此类推,直到处理完所有 100 条记录。
  • 此行为最大限度地减少了内存使用量,并避免一次将所有 100 条记录加载到内存中。

服务

@service
@requiredargsconstructor
public class customerorderservice {
    private final customerrepository customerrepository;

    @transactional(readonly = true)
    public map getcustomerordersummary(localdatetime startdate, double minorderamount) {
        try (stream customerstream = customerrepository.findcustomerwithorders(startdate)) {
            return customerstream
                    // filter customers with orders above the threshold
                    .flatmap(customer -> customer.getorders().stream()
                            .filter(order -> order.getamount() >= minorderamount)
                            .map(order -> new abstractmap.simpleentry<>(customer.getname(), order.getamount())))
                    // group by customer name and sum order amounts
                    .collect(collectors.groupingby(
                            abstractmap.simpleentry::getkey,
                            collectors.summingdouble(abstractmap.simpleentry::getvalue)
                    ));
        }
    }
}

这里是处理数据的服务类,有两个参数startdate和minorderamount。正如您所看到的,我们不使用 sql 查询进行过滤,而是将所有数据作为流加载,然后通过 java 代码进行过滤和分组。

控制器

@restcontroller
@requestmapping("/customers")
@requiredargsconstructor
public class customerordercontroller {
    private final customerorderservice customerorderservice;

    @getmapping("/orders")
    public responseentity> getcustomerordersummary(
            @requestparam @datetimeformat(iso = datetimeformat.iso.date_time) localdatetime startdate,
            @requestparam double minorderamount
    ) {
        map ordersummary = customerorderservice.getcustomerordersummary(startdate, minorderamount);
        return responseentity.ok(ordersummary);
    }
}

测试

=> 要创建测试数据,您可以在我的源代码中执行以下脚本或自己添加。

src/main/resources/dummy-data.sql

请求:

    开始日期: 2024-05-01t00:00:00
  • 最小订单金额:100
  • curl --location 'http://localhost:8090/customers/orders?startdate=2024-05-01t00%3a00%3a00&minorderamount=100'
    
回应:

    返回总金额等于或大于 minorderamount 的所有客户。
  • {
      "Jane Roe": 500.0,
      "John Doe": 150.0,
      "Bob Brown": 350.0,
      "Alice Smith": 520.0
    }
    
3. 流与列表

=> 您可以使用 intellij profiler 监控内存使用情况和执行时间。有关如何添加和测试大数据集的更多详细信息,您可以在我的 github 存储库中找到

小数据集:(10 个客户,100 个订单)

    流:执行时间(~5ms),内存使用(低)
  • 列表:执行时间(~4ms),内存使用(低)

大型数据集(10.000 个客户,100.000 个订单)

    流:执行时间(~202ms),内存使用(中等)
  • 列表:执行时间(~176ms),内存使用(高)

性能指标

metric stream list
initial fetch time slightly slower (due to lazy loading) faster (all at once)
memory consumption low (incremental processing) high (entire dataset in memory)
memory consumption low (incremental processing) high (entire dataset in memory)
processing overhead efficient for large datasets may cause memory issues for large datasets
batch fetching supported (with fetch size) not applicable
error recovery graceful with early termination limited, as data is preloaded
总结

spring data jpa 流查询方法提供了一种优雅的方式来高效处理大型数据集,同时利用 java streams 的强大功能。通过增量处理数据,它们减少了内存消耗并与现代函数式编程范例无缝集成。

您对流查询方法有何看法?在下面的评论中分享您的经验和用例!

下一篇文章见。快乐编码!

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

707

2023.10.12

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

327

2023.10.27

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

350

2024.02.23

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

1221

2024.03.06

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

360

2024.03.06

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

799

2024.04.07

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

581

2024.04.29

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

423

2024.04.29

Python 自然语言处理(NLP)基础与实战
Python 自然语言处理(NLP)基础与实战

本专题系统讲解 Python 在自然语言处理(NLP)领域的基础方法与实战应用,涵盖文本预处理(分词、去停用词)、词性标注、命名实体识别、关键词提取、情感分析,以及常用 NLP 库(NLTK、spaCy)的核心用法。通过真实文本案例,帮助学习者掌握 使用 Python 进行文本分析与语言数据处理的完整流程,适用于内容分析、舆情监测与智能文本应用场景。

10

2026.01.27

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Git 教程
Git 教程

共21课时 | 3万人学习

Git版本控制工具
Git版本控制工具

共8课时 | 1.5万人学习

Git中文开发手册
Git中文开发手册

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号