hibernate Spring Data Jpa中Group by查询的过滤器和分页

jk9hmnmh  于 2023-10-23  发布在  Spring
关注(0)|答案(1)|浏览(170)

我有一个实体如下:

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

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

我需要在field 1和field 2上使用Optionalfilter,在field 3上使用group by。我还需要对数据进行分页并返回count(*)和field 3值。same的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;

类似地,对于field 1和field 2上的过滤器。

问题:

1.要执行的查询取决于过滤器的数量。
1.查询的返回类型不是实体。
由于问题1,我不能使用直接转换为查询的spring数据方法。我也不能使用@Query,因为同样的原因。我不能在我的存储库中为每个可能的组合编写2^n个查询,其中n是过滤器的数量。
由于问题2,
我不能使用规范。我没有找到任何关于返回一组特定字段和聚合函数的规范的解决方案。

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

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

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

这是可行的,但问题是:它返回List,我必须手动将字段转换为正确的类型,并创建所需结果的列表。
谁能帮帮我。如果有其他可行的解决方案/方法,请告诉我。如果使用entityManager可以,那么告诉我,我应该怎么做,这样它就返回List而不是List。

o4tp2gmn

o4tp2gmn1#

规范可用于聚合函数。我用来数数的。下面是我如何从连接表中区分计数。代码是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
我最终做的是创建一个已经有聚合结果的DB视图,然后将一个新实体Map到该视图。现在,由于数据已经聚合,因此排序和过滤变得很简单。
这个问题被认为是查询DB视图有点慢。我假设,因为它总是做聚合,即使它不一定需要。
请注意,将实体Map到视图将始终导致聚合查询运行。即使我们不是专门过滤聚合结果,而是过滤其他结果,性能也会下降。

相关问题