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 的函数式编程特性,支持过滤、映射和收集等操作。

    易可图
    易可图

    电商人都在用的设计平台

    下载
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 的强大功能。通过增量处理数据,它们减少了内存消耗并与现代函数式编程范例无缝集成。

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

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

相关专题

更多
java
java

Java是一个通用术语,用于表示Java软件及其组件,包括“Java运行时环境 (JRE)”、“Java虚拟机 (JVM)”以及“插件”。php中文网还为大家带了Java相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

846

2023.06.15

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

745

2023.07.05

java自学难吗
java自学难吗

Java自学并不难。Java语言相对于其他一些编程语言而言,有着较为简洁和易读的语法,本专题为大家提供java自学难吗相关的文章,大家可以免费体验。

741

2023.07.31

java配置jdk环境变量
java配置jdk环境变量

Java是一种广泛使用的高级编程语言,用于开发各种类型的应用程序。为了能够在计算机上正确运行和编译Java代码,需要正确配置Java Development Kit(JDK)环境变量。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

397

2023.08.01

java保留两位小数
java保留两位小数

Java是一种广泛应用于编程领域的高级编程语言。在Java中,保留两位小数是指在进行数值计算或输出时,限制小数部分只有两位有效数字,并将多余的位数进行四舍五入或截取。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

420

2023.08.02

java基本数据类型
java基本数据类型

java基本数据类型有:1、byte;2、short;3、int;4、long;5、float;6、double;7、char;8、boolean。本专题为大家提供java基本数据类型的相关的文章、下载、课程内容,供大家免费下载体验。

447

2023.08.02

java有什么用
java有什么用

java可以开发应用程序、移动应用、Web应用、企业级应用、嵌入式系统等方面。本专题为大家提供java有什么用的相关的文章、下载、课程内容,供大家免费下载体验。

431

2023.08.02

java在线网站
java在线网站

Java在线网站是指提供Java编程学习、实践和交流平台的网络服务。近年来,随着Java语言在软件开发领域的广泛应用,越来越多的人对Java编程感兴趣,并希望能够通过在线网站来学习和提高自己的Java编程技能。php中文网给大家带来了相关的视频、教程以及文章,欢迎大家前来学习阅读和下载。

16947

2023.08.03

c++ 根号
c++ 根号

本专题整合了c++根号相关教程,阅读专题下面的文章了解更多详细内容。

58

2026.01.23

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
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号