jpa lazy使用条件api获取多个级别的实体

时间:2012-01-09 15:33:13

标签: jpa jpa-2.0 fetch criteria-api openjpa

我正在使用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);

但这不会做任何事情。

有人知道如何在一个查询中获取多级实体吗?

3 个答案:

答案 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的数据库中设计一个视图,创建实体并获取原始实体的信息。