处理 JPA 规范和 spring-data-jpa 时如何使用声明 Stream 作为返回类型

Posted

技术标签:

【中文标题】处理 JPA 规范和 spring-data-jpa 时如何使用声明 Stream 作为返回类型【英文标题】:How to use declare Stream as return type when dealing with JPA Specification and spring-data-jpa 【发布时间】:2017-05-06 18:36:08 【问题描述】:

我想知道是否可以在自定义查询中使用 JPA 规范谓词?

我试过了,但没有成功。

假设我有一个实体Customer 和一个存储库:

@Repository
public interface CustomerRepository 
    extends JpaRepository<Customer, Long>,
   JpaSpecificationExecutor<Customer> 

这样查询是可以的

@Query("select c from Customer c")
Stream<Customer> streamAllCustomers();

这样不行

Stream<Customer> streamAllCustomersWithFilter(Specification<Customer> filter);

有没有办法做到这一点?

注意,我知道我可以将参数放在 @Query 中,但我想留在当前应用程序的设计中并一直使用规范。

【问题讨论】:

没有“JPA 规范”之类的东西;那只是 Spring Data JPA API (!= JPA API)。标签固定 您的标题和问题正文中有不同的问题。您希望我们回答哪一个? 【参考方案1】:

有一种方法可以从我使用的 Spring Data JPA 流式传输数据。 这种方法有助于处理大量数据,同时避免高内存消耗,因为整个查询结果不会加载到内存中。

使用以下实现创建custom individual repository

public class YourCustomRepositoryImpl implements YourCustomRepository 

    @PersistenceContext(unitName = "yorEntityManagerFactory")
    private EntityManager em;

    @Override
    public Stream<SomeEntity> streamAll(Specification<SomeEntity> spec) 

            CriteriaBuilder cb = em.getCriteriaBuilder();
            CriteriaQuery<SomeEntity> query = cb.createQuery(SomeEntity.class);
            Root<SomeEntity> root = query.from(SomeEntity.class);
            query.where(spec.toPredicate(root, query, cb));

            return em.createQuery(query).getResultStream();
    

当然,这需要 JPA 2.2 支持 ORM 框架(我使用的是 Hibernate 5.3)。

此外,您应该注意在处理流时提供连接以保持活动状态。

【讨论】:

【参考方案2】:

TL;DR;

不,不,但手动是

我认为issue DATAJPA-906 回答了你的两个问题

    问题(来自标题):在处理 JPA 规范和 spring-data-jpa 时如何使用 declare Stream 作为返回类型?

你没有,至少没有直接支持的方式:

在 JpaSpecificationExecutor 上支持 Java 8 流

[..]

不幸的是,这将不得不等待 2.0 的改进,因为方法签名中的 Stream 会导致接口在 Java

当然你可以随时add your custom methods including implementation。

    问题我可以在自定义查询中使用 JPA 规范谓词吗?(自定义查询是使用 @Query 注释定义的查询

您如何将通过规范定义的 CriteriaQuery 和手动定义的 JPQL 查询结合起来?

如果问题不明确:如果您的自定义查询包含内部选择,规范中的标准应该放在哪里?

你能做什么

实现一个自定义方法,返回一个Stream,并将一个规范作为参数,结合准备好的规范调用JpaSpecificationExecutor接口的现有方法,并将结果转换为Stream

【讨论】:

感谢您提供指向 spring-data-jpa 问题的指针,我将等待 2.x 以获取可能“更清洁”的实现 :)

以上是关于处理 JPA 规范和 spring-data-jpa 时如何使用声明 Stream 作为返回类型的主要内容,如果未能解决你的问题,请参考以下文章

JPA 和 JDO 规范有啥区别?

JPA简介

Spring Jpa 规范和渴望加载

JPA 规范示例

JPA - 带有in子句和不区分大小写的规范

springboot分析——与其他组件的整合(JPA规范/atomikos/redis)