【问题标题】:JPA Pagination on calculated projection计算投影的 JPA 分页
【发布时间】:2022-12-08 06:13:39
【问题描述】:

我正在尝试通过 JPA 选择一些计算数据。查询看起来像这样(示例非常简单):

@Query(value = """
SELECT 
  a.field1 as f1,
  SUM(some clause using joined table) as f2,
  SUM(some other clause using joined table) as f3
FROM EntityA a
  LEFT JOIN EntityB b ON a.field1 = b.field1
WHERE a.field2 = :field2
""")
Page<ProjectionEntity> getSomeCalculatedData(String field2, Pageable pageable);

查询在没有 Pageable 参数的情况下运行良好。当我添加分页时,结果查询包含不存在的order by a.f2,因为EntityA不包含字段f2

有没有办法以查询有效的方式构建实体结构和投影?

【问题讨论】:

  • 首先,您应该对用于分页的结果进行排序。在反复执行查询时,数据库不保证结果的顺序相同,因此虽然页面大小符合预期,但您可能会看到其中一些结果出现相同的结果,或者根本看不到某些结果。我猜想,基于正在计算的 f2,Spring 的投影机制正在将它添加到您的查询中,这应该是一个错误。尝试添加您自己的订单,看看它是否停止。
  • Pageable 是分页和排序机制(正如您所写,当您对结果进行分页时,您必须对其进行排序以获得正确的结果)。问题是,从 Pageable 计算的订单字段被转换为问题中描述的实体字段。
  • 似乎您已经知道并且正在将一些东西放入您的可分页对象中,让 spring 尝试将查询修改为“按 a.f2 排序”。 Spring 不是您标记问题的 JPA/Hibernate,它是 Spring(大概)错误地确定了可分页对象应该如何修改您的查询,而不仅仅是向它添加限制/偏移值,就像它对投影。您应该将其添加到您的问题中,我建议的一个潜在解决方法是向查询定义添加排序,而不是在使用计算字段时尝试通过可分页修改它。

标签: hibernate jpa pagination


【解决方案1】:

Blaze-Persistence Entity Views 就是您要找的。

我创建了库以允许在 JPA 模型和自定义接口或抽象类定义的模型之间轻松映射,类似于 Spring Data Projections on steroids。这个想法是您按照自己喜欢的方式定义目标结构(领域模型),并通过 JPQL 表达式将属性(getter)映射到实体模型。

使用 Blaze-Persistence Entity-Views,您用例的 DTO 模型可能如下所示:

@EntityView(EntityA.class)
public interface ProjectionEntity {
    String getField1();
    @Mapping("SUM(EntityB[field1 = VIEW(field1)].amount)")
    BigDecimal getF2();
    @Mapping("SUM(EntityB[field1 = VIEW(field1)].tax)")
    BigDecimal getF3();
}

查询是将实体视图应用于查询的问题,最简单的就是通过 id 进行查询。

ProjectionEntity a = entityViewManager.find(entityManager, ProjectionEntity.class, id);

Spring Data 集成允许您几乎像使用 Spring Data Projections 一样使用它:https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features

Page<ProjectionEntity> findAll(Pageable pageable);

最好的部分是,它只会获取实际需要的状态!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-14
    • 2018-10-27
    • 1970-01-01
    • 2019-11-30
    • 2012-12-07
    • 2018-11-25
    • 1970-01-01
    相关资源
    最近更新 更多