【问题标题】:Hibernate JPA fetch joins should not be used in paged queries不应在分页查询中使用 Hibernate JPA 提取连接
【发布时间】:2020-10-26 09:48:59
【问题描述】:

Hibernate User Guide chapter 15.14 中写道:

Fetch 连接不应用于分页查询(例如 setFirstResult() 或 setMaxResults()),也不应与 scroll() 或 iterate() 特征。

没有进一步解释为什么 JPQL 查询像这样:

List<Person> persons = entityManager.createQuery(
    "select distinct pr " +
    "from Person pr " +
    "left join fetch pr.phones ", Person.class )
.setFirstResult(15)
.setMaxResults(10)
.getResultList();

应该避免。

有人能解释一下这个禁令背后的理由是什么吗?

更新

我发现 this post 解释了一切。

更新 2

更准确地说:

  1. 既然不能丢行,为什么禁止1-1惰性关系?

  2. 为什么没有在后台使用 2 个选择来实现? ( 比如:

     select pr.id from Person pr where ... pagination
     select distinct pr from Person pr left join fetch pr.phones where pr.id in (:ids_from_previous_select)
    

)

【问题讨论】:

  • 你有什么异常吗?
  • @DivyeshKanzariya 不,这是一个方法问题,更像是一种反模式。
  • 查看这篇综合帖子,特别是 join fetch 部分vladmihalcea.com/query-pagination-jpa-hibernate
  • @Aman 谢谢,但它与我在更新部分提供的链接相同。

标签: java hibernate jpa


【解决方案1】:

这是因为如果使用 JOIN 并将限制偏移量直接应用于 SQL,您最终可能会得到相关实体的截断列表。

例如,如果我们将有 PersonFriends 并且将获取前 5 条记录(首页,5 项大小),您最终会得到 1 个人和 5 个朋友,而事实上,您希望有 5 个人与所有朋友。

为了克服这个问题,hiberante 将无限制地执行整个查询,并在聚合后应用限制/偏移量。这将使例如可迭代光标根本不可迭代。

HHH000104: firstResult/maxResults specified with collection fetch; applying in memory!

【讨论】:

  • 这意味着它将从数据库中获取所有数据并在应用程序端应用限制/偏移量,这会消耗大量内存和时间。
  • 是的,完全正确。这就是为什么它不适合分页。
  • 同样的事情也适用于 OneToOne 案例吗?我没有测试它。就我个人而言,我大部分时间都避免使用投影。
  • 不,除非另有说明,否则会优先获取 1-1 关系。 1-1 关系也会产生完全相同的行数。
  • 好吧,我的意思是让 OneToOne 变得懒惰,只想在我想要的时候加入 fetch。
【解决方案2】:

一对一的关联并不禁止,这完全没问题。这只是集合的问题,即 *-to-many 关联。

我认为 Hibernate 可以适应在进行分页时更有效地获取连接,但它只是没有以这种方式实现。

我确实实现了你为 Blaze-Persistence 提到的那种分页,这是一个在 JPA/Hibernate 之上工作的库:https://persistence.blazebit.com/documentation/core/manual/en_US/index.html#pagination

其中甚至还有一些进一步的优化:

  • 在我所说的“id-query”中只完成必要的连接
  • id 查询不一定是单独的查询。事实上,默认情况下,Blaze-Persistence 将此查询内联到“object-query”中
  • Blaze-Persistence 还通过相同的 API 支持更高效的键集分页

【讨论】:

    猜你喜欢
    • 2012-02-22
    • 2012-06-05
    • 1970-01-01
    • 1970-01-01
    • 2014-09-11
    • 2017-11-28
    • 2021-12-26
    • 1970-01-01
    相关资源
    最近更新 更多