【问题标题】:jpa lazy fetch entities over multiple levels with criteria apijpa 使用标准 api 在多个级别上延迟获取实体
【发布时间】:2012-02-06 03:09:13
【问题描述】:

我正在使用 JPA2 和它的 Criteria API 从数据库中选择我的实体。实现是 WebSphere Application Server 上的 OpenJPA。我所有的实体都是用 Fetchtype=Lazy 建模的。

我从数据库中选择了一个具有某些条件的实体,并希望一次从子表中加载所有嵌套数据。 如果我有一个数据模型,其中表 A 与表 B 连接为 oneToMany,我可以在条件查询中使用 Fetch 子句:

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 元素都正确填充。 现在表 B 与表 C 具有 oneToMany 关系,我也想加载它们。所以我将以下语句添加到我的查询中:

Fetch<B,C> fetch2 = fetch.fetch(B_.elementsOfC, JoinType.LEFT);

但这不会有任何作用。

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

【问题讨论】:

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


    【解决方案1】:

    它不适用于 JPQL,也无法使其在 CriteriaQueries 中工作。规范将获取的实体限制为直接从返回的实体引用的实体:

    关于使用 CriteriaQuery 获取连接:

    fetch 方法引用的关联或属性必须是 从作为结果返回的实体或可嵌入对象引用 查询。

    关于 JPQL 中的 fetch join:

    FETCH JOIN 子句右侧引用的关联 必须是引用自的关联或元素集合 作为查询结果返回的实体或可嵌入对象。

    OpenJPA 文档中也提到了同样的限制。

    【讨论】:

    • 非常感谢您的回答。但是您指出的文档文章中有一个 JPQL 示例:SELECT x FROM Magazine x join fetch x.articles a join fetch a.publishers p WHERE x.title = 'JDJ' 有表 x、a 和 p,关系为 x->a 和 a->p。这正是我想要使用标准 API 做的事情。
    • 你没有仔细阅读。这是有关导致语法错误的查询的示例。该查询之前的句子是:“以下查询将导致语法错误:”。你想做的事没有用。
    • 哦,你是对的。所以我只能说:哎呀。但无论如何......有什么练习可以解决这样的问题吗?我认为这个世界上有很多人想要获取两张以上的桌子。我必须先加入第二个表还是应该手动读取其他数据?最好的做法是什么?
    【解决方案2】:

    您可以在连接表 b 和 c 的数据库中设计一个视图,创建实体并从原始实体中提取它。

    【讨论】:

    • 这不是一个更准确的答案,它不是问题的答案
    【解决方案3】:

    为了物有所值。我一直这样做,而且效果很好。 几点:

    我使用的是 jpa 2.1,但我几乎可以肯定它曾经也可以在 jpa 2.0 中使用。

    我正在使用标准 api,并且我知道 jpql 中有些东西的工作方式不同。所以不要认为它以某种方式起作用或不起作用,因为这就是 jpql 中发生的事情。大多数情况下,它们的行为方式相同,但并非总是如此。 (我也使用普通标准 api,没有 querydsl 或任何东西。有时它会有所作为)

    我的联想往往是 SINGULAR_ATTRIBUTE。所以也许这就是这里的问题。尝试使用反向“c.fetch(b).fetch(a)”的连接进行测试,看看是否有效。我知道它不一样,但只是看看它是否给你任何提示。不过,我几乎可以肯定我也使用了 onetomany left fetch joins。

    是的。我刚刚检查并找到它: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
    

    并返回与所有字段关联的所有行。

    也许问题是另一回事。你只是说“它不会做任何事情”。我不知道它是否抛出异常或什么,但它可能正确执行查询,但由于某些条件或类似情况而没有返回您期望的行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-15
      • 1970-01-01
      • 2013-05-21
      • 2023-03-17
      • 1970-01-01
      • 2012-10-05
      相关资源
      最近更新 更多