带有两个子查询/连接的 JPA 标准选择

Posted

技术标签:

【中文标题】带有两个子查询/连接的 JPA 标准选择【英文标题】:JPA Criteria select with two subqueries / joins 【发布时间】:2016-01-13 22:03:52 【问题描述】:

我整天都在战斗,我想不通。我是 JPA 初学者,所以现在 Criteria API 对我来说是一场噩梦。问题:

我有 3 个实体:Policy、Customer、Insurer。保单引用了客户和保险公司(此处急切获取)。客户有保单清单,Insurer 也有(这里是懒惰的获取)。

我正在尝试以下述方式 (SQL) 查找所有策略:


SELECT * FROM POLICY as p WHERE
p.CUSTOMER_ID IN (SELECT ID FROM CUSTOMER as c WHERE [customerPredicates])
AND
p.INSURER_ID IN (SELECT ID FROM INSURER as i WHERE [insurerPredicates])
AND
[policyPredicates]

其中 CUSTOMER_ID / INSURER_ID 是从 Policy 中的 @ManyToOne 关系生成的 JoinColumns。

customerPredicates / insurancePredicates / policyPredicates 是谓词列表(根据给定搜索条件准备的“where”条件)。

如何在 Criteria API 中实现这一点?创建此类查询的规则/良好做法是什么?

【问题讨论】:

【参考方案1】:

尝试先重写 SQL 以使用 JOINS

SELECT * 
FROM POLICY as p 
     INNER JOIN CUSTOMER as c ON p.CUSTOMER_ID = c.ID
     INNER JOIN INSURER as i ON p.INSURER_ID = i.ID
WHERE [customerPredicates])
AND
[insurerPredicates])
AND
[policyPredicates]

您所需要的只是标准 api,用于获取主要标准(用于 Policy 实体)并为 Customer 实体和 Insurer 实体创建别名。

    Criteria criteria = session.createCriteria(Policy.class, "p");
    criteria.setFetchMode("p.Customer", FetchMode.JOIN);
    criteria.createAlias("p.Customer", "c");

并将您的限制添加到 Customer 的“c”别名。

保险公司也是如此

【讨论】:

是的,重写这个 SQL 可以帮助我解决这个问题,但我想使用纯 JPA Criteria API,而不是 Hibernate 的 Crtiteria。我试图理解 JPA Criteria 中的获取和别名,但我感到困惑...... JPA 也有别名。所以你可以使用与纯 JPA Criteria API 相同的逻辑

以上是关于带有两个子查询/连接的 JPA 标准选择的主要内容,如果未能解决你的问题,请参考以下文章

选择带有“is null”子句的查询和子选择/左连接不返回结果

from 子句中的 JPA/hibernate 子查询

在 JPA 的 SQL 查询中的 FROM 语句中包含子查询

Oracle通过带有内部连接和返回n行的子查询的桥表选择查询?

在连接的子查询中重复 WHERE 标准

SQL 从带有子查询的多个表中选择数据(包括来自内部连接的数据)错误:1242