我正在使用JPA2和它的Criteria API来从数据库中选择我的实体。实现是WebSphere Application Server上的OpenJPA。我的所有实体都使用Fetchtype = Lazy建模。
我从数据库中选择一个具有某些条件的实体,并希望一次从子表中加载所有嵌套数据。 如果我有一个数据模型,表A将oneToMany连接到表B,我可以在条件查询中使用Fetch-clause:
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<A> cq = cb.createQuery(A.class);
Root<A> root = cq.from(A.class);
Fetch<A,B> fetch = root.fetch(A_.elementsOfB, JoinType.LEFT);
这很好用。我得到一个元素A,它的所有元素都被正确填充。 现在表B与表C有一个oneToMany关系,我也想加载它们。所以我在我的查询中添加以下语句:
Fetch<B,C> fetch2 = fetch.fetch(B_.elementsOfC, JoinType.LEFT);
但这不会做任何事情。
有人知道如何在一个查询中获取多级实体吗?
答案 0 :(得分:10)
它不适用于JPQL,也无法使其在CriteriaQueries中正常工作。规范将获取的实体限制为直接从返回的实体引用的实体:
关于使用CriteriaQuery进行提取连接:
fetch方法引用的关联或属性必须是 从实体引用或作为结果返回的embeddable引用 查询。
关于JPQL中的提取连接:
FETCH JOIN子句右侧引用的关联 必须是引用的关联或元素集合 作为查询结果返回的实体或嵌入式。
OpenJPA文档中也说明了相同的限制。
答案 1 :(得分:0)
为了什么值得。我一直都这样做,而且效果很好。 几点:
我正在使用jpa 2.1,但几乎可以肯定它也可以在jpa 2.0中使用。
我正在使用条件api,而且我知道jpql中的某些功能不同。因此,不要以为它会起作用或不起作用,因为这就是jpql中发生的情况。大多数情况下,它们的行为方式相同,但并非总是如此。 (此外,我使用的是普通条件api,没有querydsl或其他任何东西。有时会有所不同)
我的关联通常是SINGULAR_ATTRIBUTE。所以也许这就是这里的问题。尝试使用反向连接“ c.fetch(b).fetch(a)”进行测试,看看是否可行。我知道这是不一样的,只是看它是否能给您任何提示。不过,我几乎可以肯定,我也已经使用onetomany左访存连接来做到这一点。
是的。我刚刚检查并找到了它:root.fetch("targets", LEFT).fetch("destinations", LEFT).fetch("internal", LEFT)
几个月来,甚至一年以上,一直没有问题。
我只是运行一个测试,它会生成以下查询:
select -- all fields from all tables
...
from agreement a
left outer join target t on a.id = t.agreement_id
left outer join destination d on t.id = d.target_id
left outer join internal i on d.id = i.destination_id
并返回具有与所有字段的所有关联的所有行。
也许问题是另外一回事。您只是说“它不会做什么”。我不知道它是否引发异常或什么,但是也许它可以正确执行查询,但是由于某些条件或类似的原因,它不会返回您期望的行。
答案 2 :(得分:-2)
您可以在连接表b和c的数据库中设计一个视图,创建实体并获取原始实体的信息。