给定以下域模型,我想加载所有Answer
包括他们的Value
s 及其各自的子孩子并将其放入AnswerDTO
然后转换为 JSON。我有一个可行的解决方案,但它遇到了 N+1 问题,我想通过使用临时解决方案来摆脱它@EntityGraph
。所有关联均已配置LAZY
.
@Query("SELECT a FROM Answer a")
@EntityGraph(attributePaths = {"value"})
public List<Answer> findAll();
使用临时@EntityGraph
on the Repository
方法我可以确保预取值以防止 N+1Answer->Value
协会。虽然我的结果很好,但还有另一个 N+1 问题,因为延迟加载selected
的协会MCValue
s.
使用这个
@EntityGraph(attributePaths = {"value.selected"})
失败,因为selected
领域当然只是某些领域的一部分Value
实体:
Unable to locate Attribute with the the given name [selected] on this ManagedType [x.model.Value];
我怎样才能告诉 JPA 只尝试获取selected
关联,如果该值为 aMCValue
?我需要类似的东西optionalAttributePaths
.
您只能使用一个EntityGraph https://thoughts-on-java.org/jpa-21-entity-graph-part-1-named-entity/如果关联属性是超类的一部分并且也是所有子类的一部分。否则,EntityGraph
总是会失败Exception
您目前得到的。
避免 N+1 选择问题的最佳方法是将查询拆分为 2 个查询:
第一个查询获取MCValue
实体使用EntityGraph
获取映射的关联selected
属性。在该查询之后,这些实体将被存储在 Hibernate 的一级缓存/持久化上下文中。 Hibernate 将在处理第二个查询的结果时使用它们。
@Query("SELECT m FROM MCValue m") // add WHERE clause as needed ...
@EntityGraph(attributePaths = {"selected"})
public List<MCValue> findAll();
然后第二个查询获取Answer
实体并使用EntityGraph
还可以获取关联的Value
实体。对于每个Value
实体,Hibernate 将实例化特定的子类并检查一级缓存是否已包含该类和主键组合的对象。如果是这种情况,Hibernate 将使用一级缓存中的对象,而不是查询返回的数据。
@Query("SELECT a FROM Answer a")
@EntityGraph(attributePaths = {"value"})
public List<Answer> findAll();
因为我们已经获取了所有MCValue
具有关联的实体selected
实体,我们现在得到Answer
具有初始化的实体value
协会。如果关联包含MCValue
实体,其selected
关联也将被初始化。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)