【问题标题】:Java JPA repository slow on readingJava JPA 存储库读取速度慢
【发布时间】:2018-04-25 10:29:41
【问题描述】:

我有一个包含相当大实体模型的数据库。 总共有 14 个表,平均记录约 10 万条。

当我测试我的应用程序从数据库中获取一个实体并将其转换为 json 并将其返回给调用者时,需要 7 秒才能获取条目。

这似乎不是初始化问题,因为如果我连续两次执行相同的调用,它们都需要大约 10 秒才能获取数据。

当我启用 sql 脚本日志记录时,我发现对于每个读取的实体,hibernate 都会向数据库发送数百个 sql 请求。 (实际数量基于实体有多少连接/许可证/产品/服务等,但对于我的测试条目,我收到了 286 个查询(总共花费了大约 7 秒)) 当数据库为空时(测试应该返回的数据除外),大约需要 6 秒。

我想问题是因为我将 @OneToMany 和 @ManyToMany 的 fetch 设置为 Lazy,但是当我将它们设置为 Eager 时,我收到多个 fetch bag 的错误。

@javax.persistence.OneToMany(fetch = javax.persistence.FetchType.LAZY)
@org.hibernate.annotations.LazyCollection(org.hibernate.annotations.LazyCollectionOption.FALSE)
@javax.persistence.JoinColumn(name = "ProductId")

这是我拥有的 OneToMany 关系的一个示例,它模拟了没有多个 fetch bag 错误的 Eager fetch。

这是一个常见问题吗? 以及如何提高阅读速度?

【问题讨论】:

  • 您的 JSON 文档有多大,有多少关系? Fetch 类型通常应该是惰性的,但如果您需要阅读世界,那将总是很慢。如果空表中的单个实体需要 6 秒,那么它一定是巨大的!
  • 生成的 json 长 2652 行,由来自数据库的总共 502 条记录组成
  • 去掉 Hibernate 特有的 LazyCollection 注解,你会得到与便携式 FetchType.EAGER 相同的效果(我一般不推荐)。然后看看有多少查询?你是做 502 次选择,还是有一些选择有很多结果?
  • 如果我将获取类型设置为渴望,我会得到一个 MultipleBagFetchException,LazyCollection 注释是解决方案,我不确定是否存在其他解决方案
  • 我不想使用急切获取,我建议按照下面的答案使用连接获取或获取图,或者更改批量大小以进行读取。但是,为了做到这一点,我想知道当系统使用延迟获取时有多少个选择以及有多少个表?

标签: java sql-server hibernate spring-data-jpa


【解决方案1】:

Hibernate 不允许将多个 List 类型的集合标记为 EAGER。

加载数据的最佳方法是使用 JOIN FETCH

select e from YourEntity JOIN FETCH e.yourList l

另一种选择是使用 EntityGraph 来定义 EAGER 加载。

在此处阅读有关该主题的更多信息:

https://vladmihalcea.com/hibernate-facts-the-importance-of-fetch-strategy/

如果您使用 Spring Data JPA 存储库接口,您可以使用 NamedEntityGraphs:

https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.entity-graph

【讨论】:

  • 虽然我没有使用 JPQL 查询,但我使用的是 org.springframework.data.jpa.repository.JpaRepository,它根据接口的方法名称进行查询。我更喜欢保留存储库方法,因为使用它来模拟数据库非常容易
  • 那我推荐使用EntityGraphs。请参阅我的更新答案。
  • 据我所知,它只是将查询更早地拉入流程,但不会减少完成的查询数量。
  • 您遇到了经典的 n+1 读取问题。有几种方法可以解决这个问题:stackoverflow.com/questions/97197/…
猜你喜欢
  • 2019-02-05
  • 2021-10-23
  • 2019-02-09
  • 1970-01-01
  • 1970-01-01
  • 2016-05-28
  • 1970-01-01
  • 1970-01-01
  • 2020-04-27
相关资源
最近更新 更多