【问题标题】:Spring JPA Repositories with Stream<Entity>带有 Stream<Entity> 的 Spring JPA 存储库
【发布时间】:2021-07-12 23:29:35
【问题描述】:

我不明白 Stream&lt;&gt; 返回类型与存储库方法的 List&lt;&gt; 有何不同。

我在下面用 fetch size = 1 写了一个简单的方法,但我最终从表中获取了所有 4 条记录,这类似于 List。我错过了什么吗?它是否应该只获取HINT_FETCH_SIZE 中指定的 1 条记录。如果它获取 1 条记录,那么剩余的 3 条记录是如何获取的?完成了多少次数据库调用?

@QueryHints(value = {
        @QueryHint(name = HINT_FETCH_SIZE, value = "1"),
        @QueryHint(name = HINT_CACHEABLE, value = "false"),
        @QueryHint(name = HINT_READONLY, value = "true"), })
@Query("SELECT s FROM Customer s")
public Stream<Customer> findAllStream8();

服务:

@Transactional(readOnly = true)
public List<Customer> findAllStream(){
    try (Stream<Customer> streamCustomer = repository.findAllStream8()){
        return streamCustomer.collect(Collectors.toList());
    } catch (Exception e){
        e.printStackTrace();
    }
    return Arrays.asList(new Customer("stream customer"));
}

控制器:

@GetMapping("/customer/allStream")
public List<Customer> findAllCustomersStream(){
    return cs.findAllStream();
}

【问题讨论】:

    标签: java spring spring-data-jpa java-stream


    【解决方案1】:

    baeldung article

    Spring Data 使用特定于提供程序的实现来流式传输结果 (Hibernate 使用 ScrollableResultSet,EclipseLink 使用 可滚动光标)。它减少了内存消耗和 查询对数据库的调用。正因为如此,它也比 前面提到的两种解决方案。

    检查hibernate对此的状态

    Query Streaming

    调用collect方法后自动关闭Stream, 因为没有理由保持底层 JDBC ResultSet 打开,如果 Stream 不能重复使用

    查询流只是为了更好地分配资源和内存而发明的一种新机制。

    在以下行中的示例中

     return streamCustomer.collect(Collectors.toList());
    

    在收集期间,您让它从数据库中读取所有实体并将它们收集到一个列表中。根据您的喜好,我怀疑每次读取 1 行(1 个实体客户)时它会在数据库中执行 4 次

    如果在流式传输期间您跳过了我在上面发布的来自休眠的查询流式传输链接中指示的一些元素,它就不会从数据库中读取这些元素。

    如果你有streamCustomer.skip(2).collect(Collectors.toList());

    它只会从数据库中读取 2 个元素,并且会访问数据库 2 次。由于您会从流中跳过 2 个元素,因此不需要带上这些元素。

    如果你有 streamCustomer.limit(3).collect(Collectors.toList());

    它会从该流中读取 3 个实体并将它们收集到您的列表中。所以它会访问数据库 3 次,每次获取 1 行(1 个客户实体)。

    我认为这是更好地分配内存和资源的方式。

    【讨论】:

      【解决方案2】:

      您的第一个问题在这里得到了很好的回答:https://stackoverflow.com/a/63127616/13210306

      关于您的代码,HINT_FETCH_SIZE 用于限制每次迭代中获取的项目数,直到它到达所有项目。它将为每次迭代获取 1 个项目,在您的情况下为 4 次迭代。

      为了限制返回项目的数量,您可以使用按名称限制查询(例如:findFirst() 或 findTop1())。看这里:https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.limit-query-result

      或者你可以使用setMaxResults()来限制你的查询结果。

      criteria.setMaxResults(1);
      

      【讨论】:

        猜你喜欢
        • 2016-03-26
        • 1970-01-01
        • 2017-03-16
        • 1970-01-01
        • 2021-11-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-09-09
        相关资源
        最近更新 更多