如何在JPQL中进行“深度”获取连接?

时间:2013-05-21 22:34:03

标签: jpa jpql

我认为我不会完全理解fetch连接。

我有一个查询,我试图热切地“夸大”两个级别的参考文献。

也就是说,我的A有一个Collection BBCBAB。已知FetchType.LAZY集合的大小很小(10-20个顶部)。我想预取这张图。

B的{​​{1}}关系标记为C并且是可选的。 FetchType.LAZYSELECT a FROM A a LEFT JOIN FETCH a.bs // look, no alias; JPQL forbids it LEFT JOIN a.bs b // "repeated" join necessary since you can't alias fetch joins LEFT JOIN FETCH b.c // this doesn't seem to do anything WHERE a.id = :id 的关系也是可选的A

我希望我能做到:

B

当我运行它时,我看到确实提取了LEFT JOIN s B集合(我在SQL中看到C引用C映射到的表)。

但是,我没有看到提取B表的证据。

如何从给定的C预取所有A以及所有{{1}}和所有{{1}}的“可到达”?我看不到任何办法。

4 个答案:

答案 0 :(得分:5)

JPA规范不允许对提取连接进行别名,但有些JPA提供程序会这样做。

EclipseLink从2.4开始。 EclipseLink还允许使用点表示法(即“JOIN FETCH a.bs.c”)进行嵌套连接提取,并支持允许嵌套连接的查询提示“eclipselink.join-fetch”(您可以指定相同提示名称的多个提示) )。

通常,在提取连接上使用别名时需要小心,因为您可能会影响返回的数据。

请参阅, http://java-persistence-performance.blogspot.com/2012/04/objects-vs-data-and-filtering-join.html

答案 1 :(得分:4)

  

JPA不允许嵌套连接提取,也不允许连接上的别名   fetch,所以这可能是JPA提供者特有的。

     

在EclipseLink中,您可以指定查询提示以执行嵌套连接   取。

     

你不能在JPQL中使它递归,你只能充其量只能去   n级。在EclipseLink中,您可以使用@JoinFetch或@BatchFetch   映射使查询递归。

     

请参阅,   http://java-persistence-performance.blogspot.com/2010/08/batch-fetching-optimizing-object-graph.html

来源:http://www.coderanch.com/t/570828/ORM/databases/Recursive-fetch-join-recursively-fetching

答案 2 :(得分:3)

我正在使用Hibernate(这可能是特定的)并且我已经成功了:

SELECT DISTINCT a, b 
FROM A a
LEFT JOIN a.bs b
LEFT JOIN FETCH a.bs
LEFT JOIN FETCH b.c
WHERE a.id = :id

(请注意选择列表中的b)。

这是我发现这对我有用的唯一方法,请注意这会为我返回Object[]然后我会在代码中过滤它:

(List<A>) q.getResultList().stream().map(pair -> (A) (((Object[])pair)[0])).distinct().collect(Collectors.toList());

答案 3 :(得分:1)

不完全是JPQL,但是您可以使用Criteria查询在纯JPA中实现:

CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<MyEntity> q = cb.createQuery(MyEntity.class);
Root<MyEntity> root = q.from(MyEntity.class);
q.select(root);
Fetch bsFetch = root.fetch("bs", JoinType.LEFT);
bsFetch.fetch("c", JoinType.LEFT);

对此类型的嵌套提取的支持是特定于供应商的(因为JPA不需要它们这样做),但是eclipselink和hibernate都支持它,这样您的代码就保持与供应商无关。