18

我认为我永远不会完全理解 fetch joins。

我有一个查询,我正试图急切地将引用“膨胀”到两个级别。

也就是说, myA有一个可选CollectionBs,每个B都有 0 或 1 C。已知该B系列的尺寸很小(10-20 顶)。我想预取这张图。

AB关系被标记为FetchType.LAZY并且是可选的。 B的关系C也是可选的,并且FetchType.LAZY

我希望我能做到:

SELECT 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

当我运行它时,我看到确实提取了As集合(我在 SQL 中看到 a 引用了映射到的表)。BLEFT JOINB

但是,我没有看到这样的证据表明C's 表已被提取。

如何从给定预取所有“可访问”的Cs 和所有Bs 和所有s ?我看不出有任何方法可以做到这一点。CA

4

4 回答 4

6

JPA 规范不允许为 fetch join 设置别名,但一些 JPA 提供程序允许。

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

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

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

于 2013-05-22T13:51:15.183 回答
5

我正在使用 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());
于 2016-02-26T15:41:41.100 回答
4

JPA 不允许嵌套连接提取,也不允许连接提取上的别名,因此这可能是 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

于 2013-05-21T23:18:01.357 回答
4

不完全是 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("b", JoinType.LEFT); //fetch b, property of MyEntity and hold fetch object
bsFetch.fetch("c", JoinType.LEFT); //fetch c, property of b

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

于 2019-04-29T14:54:25.243 回答