JPA继承@EntityGraph包括子类的可选关联 [英] JPA inheritance @EntityGraph include optional associations of subclasses

查看:329
本文介绍了JPA继承@EntityGraph包括子类的可选关联的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

鉴于以下域模型,我想加载所有Answer包括其Value及其各自的子子级,并将其放入AnswerDTO中,然后转换为JSON.我有一个可行的解决方案,但是它遇到了N + 1问题,我想通过使用临时@EntityGraph摆脱它.所有关联都配置为LAZY.

Given the following domain model, I want to load all Answers including their Values and their respective sub-children and put it in an AnswerDTO to then convert to JSON. I have a working solution but it suffers from the N+1 problem that I want to get rid of by using an ad-hoc @EntityGraph. All associations are configured LAZY.

@Query("SELECT a FROM Answer a")
@EntityGraph(attributePaths = {"value"})
public List<Answer> findAll();

Repository方法上使用临时的@EntityGraph,我可以确保预先提取值以防止Answer->Value关联上的N + 1.虽然我的结果还不错,但是还有另一个N + 1问题,因为延迟加载了MCValueselected关联.

Using an ad-hoc @EntityGraph on the Repository method I can ensure that the values are pre-fetched to prevent N+1 on the Answer->Value association. While my result is fine there is another N+1 problem, because of lazy loading the selected association of the MCValues.

使用此

@EntityGraph(attributePaths = {"value.selected"})

失败,因为selected字段当然只是某些Value实体的一部分:

fails, because the selected field is of course only part of some of the Value entities:

Unable to locate Attribute  with the the given name [selected] on this ManagedType [x.model.Value];

如果值是MCValue,如何告诉JPA仅尝试获取selected关联?我需要类似optionalAttributePaths的东西.

How can I tell JPA only try fetching the selected association in case the value is a MCValue? I need something like optionalAttributePaths.

推荐答案

您只能使用

You can only use an EntityGraph if the association attribute is part of the superclass and by that also part of all subclasses. Otherwise, the EntityGraph will always fail with the Exception that you currently get.

避免N + 1选择问题的最佳方法是将查询分为2个查询:

The best way to avoid your N+1 select issue is to split your query into 2 queries:

第一个查询使用获取MCValue实体,以获取由selected属性映射的关联.在查询之后,这些实体随后存储在Hibernate的1级缓存/持久性上下文中. Hibernate在处理第二个查询的结果时将使用它们.

The 1st query fetches the MCValue entities using an EntityGraph to fetch the association mapped by the selected attribute. After that query, these entities are then stored in Hibernate's 1st level cache / the persistence context. Hibernate will use them when it processes the result of the 2nd query.

@Query("SELECT m FROM MCValue m") // add WHERE clause as needed ...
@EntityGraph(attributePaths = {"selected"})
public List<MCValue> findAll();

然后,第二个查询获取Answer实体,并使用EntityGraph还获取关联的Value实体.对于每个Value实体,Hibernate将实例化特定的子类并检查一级缓存是否已包含该类和主键组合的对象.如果是这种情况,Hibernate将使用一级缓存中的对象,而不是查询返回的数据.

The 2nd query then fetches the Answer entity and uses an EntityGraph to also fetch the associated Value entities. For each Value entity, Hibernate will instantiate the specific subclass and check if the 1st level cache already contains an object for that class and primary key combination. If that's the case, Hibernate uses the object from the 1st level cache instead of the data returned by the query.

@Query("SELECT a FROM Answer a")
@EntityGraph(attributePaths = {"value"})
public List<Answer> findAll();

因为我们已经获取了所有具有关联的selected实体的MCValue实体,所以我们现在获得具有已初始化的value关联的Answer实体.并且,如果关联包含MCValue实体,则其selected关联也将被初始化.

Because we already fetched all MCValue entities with the associated selected entities, we now get Answer entities with an initialized value association. And if the association contains an MCValue entity, its selected association will also be initialized.

这篇关于JPA继承@EntityGraph包括子类的可选关联的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆