Java 如何从具有多个计数和分组查询的Spring数据JPA返回可分页自定义对象?

Java 如何从具有多个计数和分组查询的Spring数据JPA返回可分页自定义对象?,java,spring,hibernate,jpa,spring-data-jpa,Java,Spring,Hibernate,Jpa,Spring Data Jpa,我做了这件事 以下两种方法findLaptopTotalQty和findLaptopQtySummary运行良好 @Query("SELECT " + "new com.path.to.LaptopModelCount" + "(l.laptopModel AS laptopModel, COUNT(l.laptopModel) AS qty) " + "FROM Laptop

我做了这件事

以下两种方法
findLaptopTotalQty
findLaptopQtySummary
运行良好

@Query("SELECT "
        + "new com.path.to.LaptopModelCount"
        + "(l.laptopModel AS laptopModel, COUNT(l.laptopModel) AS qty) "
        + "FROM Laptop l "
        + "GROUP by l.laptopModel")
Page<LaptopModelCount> findLaptopTotalQty(Pageable pageable);


@Query("SELECT "
            + "new com.path.to.LaptopModelCount"
            + "(l.laptopModel AS laptopModel, COUNT(l.laptopModel) AS qty,"
            + "sum(case when l.status = 'ready' then 1 else 0 end) AS ready," 
            + "sum(case when l.status = 'partsOnly' then 1 else 0 end) AS partsOnly)"
            + "FROM Laptop l "
            + "GROUP by l.laptopModel")
List<LaptopModelCount> findLaptopQtySummary();

我猜Spring数据并不支持这一点,但我不确定

然而,这是一个完美的用例

Blaze Persistence是JPA之上的查询生成器,它支持JPA模型之上的许多高级DBMS功能。我在它上面创建了实体视图,以便在JPA模型和自定义接口定义的模型之间轻松映射,类似于类固醇上的Spring数据投影。其思想是以您喜欢的方式定义目标结构,并通过JPQL表达式将属性(getter)映射到实体模型。由于属性名被用作默认映射,您基本上不需要显式映射,因为80%的用例都需要DTO作为实体模型的子集

带有实体视图的投影可以像下面这样简单

@EntityView(Laptop.class)
interface LaptopModelCount {
    @IdMapping
    long getLaptopModel();
    @Mapping("COUNT(*)")
    long getQty();
    @Mapping("COUNT(*) FILTER (WHERE status = 'ready')")
    long getReady();
    @Mapping("COUNT(*) FILTER (WHERE status = 'partsOnly')")
    long getPartsOnly();
}
查询是将实体视图应用于查询的问题,最简单的就是按id进行查询

laptomodelcount dto=entityViewManager.find(entityManager,laptomodelcount.class,id)

但是Spring数据集成允许您像使用Spring数据投影一样使用它:

这将准确地创建您所期望的查询,并可用于分页

Page<LaptopModelCount> findAll(Pageable pageable);
在这种情况下,您可以调用
EntityViewSetting.fetch(“qty”)
来覆盖实际应该获取的内容,这似乎是您在使用具有不同需求的同一模型时所需要的

@EntityView(Laptop.class)
interface LaptopModelCount {
    @IdMapping
    long getLaptopModel();
    @Mapping("COUNT(*)")
    long getQty();
    @Mapping("COUNT(*) FILTER (WHERE status = 'ready')")
    long getReady();
    @Mapping("COUNT(*) FILTER (WHERE status = 'partsOnly')")
    long getPartsOnly();
}
Page<LaptopModelCount> findAll(Pageable pageable);
List<LaptopModelCount> findAll(EntityViewSettingProcessor<LaptopModelCount> processor);