【问题标题】:How to join unrelated entities with the JPA Criteria API如何使用 JPA Criteria API 连接不相关的实体
【发布时间】:2013-06-10 23:33:41
【问题描述】:

两个数据库表有外键关系。

它们被 JPA 映射到两个实体 AB,但是连接列是手动从实体中删除的,因此在 JPA 世界类中 A 和 B 不相关,您无法通过字段/属性从一个导航到另一个。

使用 JPA Criteria API,是否可以创建连接两个表的查询?

我在互联网上找到的所有示例都使用 join 列来实现目标,但是如上所述,它已从代码中删除,因为大多数时候我对 A 之间的关系不感兴趣和 B,我担心可能的开销。

【问题讨论】:

    标签: java jpa join associations criteria-api


    【解决方案1】:

    首先:外键关系不仅仅用于导航。它们主要用于确保关系中没有引入虚假值。它们还可以帮助数据库进行查询优化。我建议你重新考虑一下。

    无论如何,要创建一个使用多个不相关实体的查询,您需要将它们设置为 from (root) 实体(就像在 SQL 或 JPQL 中所做的那样)

    SELECT .... FROM Link l, Training t WHERE l.attribute = t.attribute;
    
    Root<Link> rootLink = criteriaQuery.from(Link.class);
    Root<Training> rootTraining = criteriaQuery.from(Training.class);
    ...
    criteriaQuery.where(
        criteriaBuilder.equal(rootLink.get(link_.linkAttribute), trainingLink));
    

    【讨论】:

    • 值得注意的是,使用多个根会在实体之间创建一个笛卡尔积(即CROSS JOIN)。使用WHERE 条件,这与INNER JOIN 的行为相同(包括与here 相同的性能)。
    • 我不明白这个答案。 trainingLink 来自哪里?我不想要criteriaBuilder.equal(rootLink.get(link_.linkAttribute), rootTraining.get(training_.linkAttribute 之类的东西(不适用于标准api)吗?
    • 你能不能也展开...,从两个表Link和Training中选择不同的列
    【解决方案2】:

    从 Hibernate 5.1 开始,您可以在使用 JPQL 和 HQL 时加入不相关的实体:

    Tuple postViewCount = entityManager.createQuery(
        "select p as post, count(pv) as page_views " +
        "from Post p " +
        "left join PageView pv on p.slug = pv.slug " +
        "where p.title = :title " +
        "group by p", Tuple.class)
    .setParameter("title", "Presentations")
    .getSingleResult();
    

    但是,此功能在 Criteria API 中不可用,因为这需要 API 扩展。

    解决方案

    虽然您可以尝试使用两个 Root 对象并通过 WHERE 子句谓词模拟 INNER JOIN,但生成的 SQL 并不是解决此问题的最佳方法。

    您应该考虑使用jOOQ,因为除了让您能够以任何可能的方式连接表之外,如果您将生成的 SQL 查询传递给 JPA createNativeQuery 方法,您还可以获取实体。

    【讨论】:

      【解决方案3】:

      最新的 JPA 规范 (2.1) 未涵盖不相关实体的联接

      但是 Hibernate 5.1.0+ 和 EclipseLink 2.4.0+ 支持 ad hoc join。 http://blog.anthavio.net/2016/03/join-unrelated-entities-in-jpa.html

      另一种可能性是原生查询 http://www.oracle.com/technetwork/articles/vasiliev-jpql-087123.html

      【讨论】:

      • 第一个链接坏了。您能否提供一个替代链接,或者(更好地)给我们一个链接告诉我们做什么的摘要?
      【解决方案4】:

      您可以使用 Blaze-persistence 的 JPA Criteria 实现,该实现可转换为 JPQL/HQL,并提供该功能作为 JPA Criteria API 的扩展。

      在自述文件中查找“Blaze-Persistence JPA-Criteria 模块依赖项”:https://github.com/Blazebit/blaze-persistence/blob/master/README.md

      然后使用BlazeCriteriaBuilder cb = BlazeCriteria.get(criteriaBuilderFactory),最后使用blazeCriteriaQuery.getCriteriaBuilder(entityManager) 来呈现JPA Criteria Query 对象。

      【讨论】:

        【解决方案5】:

        可以为连接查询创建视图并为此视图创建实体,并且 JpaRepository 可以与用于表的通常实体类似地使用。 如果你需要动态构建 where 子句,在这个视图实体之上构建它仍然是可行的

        【讨论】:

          猜你喜欢
          • 2012-08-03
          • 2015-08-14
          • 1970-01-01
          • 1970-01-01
          • 2018-07-04
          • 2017-06-09
          • 1970-01-01
          • 2018-10-16
          • 2012-03-15
          相关资源
          最近更新 更多