Spring Data Jpa 中的分组查询过滤器和分页

问题描述 投票:0回答:1

我有一个实体如下:

@Entity
public class Something {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    private String field1;
    private String field2;
    private String field3;
    //@Getters and @Setters
}

我需要在 field1、field2 上使用 Optional 过滤器,并在 field3 上使用 group by 。我还需要对数据进行分页并返回 count(*) 和 field3 值。相同的sql查询是(不带过滤器)

select field3, count(*) as number from something  group by field3 LIMIT 0,10;

带 1 个过滤器:

select field3, count(*) as number from somethhing where field1=:field1 group by field3 LIMIT 0,10;

类似地,对于 field1 和 field2 上的过滤器。

问题:

  1. 要执行的查询取决于过滤器的数量。

  2. 查询的返回类型不是实体。

由于问题1,我无法使用直接转换为查询的spring data方法。出于同样的原因,我也不能使用@Query。我无法在我的存储库中为每个可能的组合编写 2^n 个查询,其中 n 是过滤器的数量。

由于问题2,

我无法使用规格。我没有找到任何具有返回一组特定字段和聚合函数规范的解决方案。

到目前为止我的解决方案:

我使用了实体管理器并根据参数的数量创建了一个查询。 现在我这样使用它:

List<Object[]> resultData = entityManager.createNativeQuery(query).getResultList();

它有效,但问题是:它返回列表,我必须手动将字段转换为正确的类型并创建所需结果的列表。

有人可以帮助我吗?如果有其他可行的解决方案/方法,请告诉我。如果使用实体管理器没问题,那么让我知道我应该做什么,以便它返回我列表而不是列表。

hibernate spring-data-jpa hibernate-mapping hibernate-criteria
1个回答
0
投票

规范可用于聚合函数。我用它来数数。 以下是我如何计算与连接表不同的计数。代码是 kotlin 但易于理解:

过滤:

val subQuery = query.subquery(Long::class.java)
val subRoot = subQuery.from(SomeJoinEntity::class.java)
val subJoin = subRoot.join<SomeJoinEntity, SomeRootEntity>("joinAttribute", JoinType.LEFT)

val subQueryCount = subQuery.select(cb.countDistinct(subRoot.get<String>("attributeToBeCounted")))
    subQuery.where(cb.equal(root.get<Any>("id"), subJoin.get<Any>("idJoin")))

排序:

val path = root.join<Any, Any>("joinAttribute", JoinType.LEFT)
        .get<String>("attributeToBeCounted")
query.orderBy(cb.asc(cb.countDistinct(path)))
if(query.groupList.isEmpty()) query.groupBy(root.get<Long>("id"))

问题是,如果使用group by,记录总数将会关闭。 Spring 团队表示该规范仅用于 WHERE 子句,尽管 api 允许我们进行分组。

这是针对该主题的 Spring 讨论:https://github.com/spring-projects/spring-data-jpa/pull/2376

我最终要做的是创建一个数据库视图,其中已经包含聚合结果,然后将一个新实体映射到该视图。 现在排序和过滤很简单,因为数据已经聚合。

© www.soinside.com 2019 - 2024. All rights reserved.