JPA 支持没有对象关系映射的外部连接

Posted

技术标签:

【中文标题】JPA 支持没有对象关系映射的外部连接【英文标题】:JPA support for outer joins without object relational mapping 【发布时间】:2015-09-23 03:26:45 【问题描述】:

最近我不得不在两个没有对象关系映射的 JPA 实体之间使用外连接。根据规范和论坛帖子,只有在 JPA 级别映射实体时才支持外部联接。

下面的示例代码。要求是找到没有任何订单的客户。

@Entity
class Customer 
    private int id;

@Entity
class Order 
    private int customerId;
    public int getCustomerId()  return customerId; 
    public void setCustomerId(int customerId)  this.customerId = customerId ; 

就我而言,我必须选择原生查询来完成工作。

对于未来的 JPA 规范是否支持没有关系映射的外连接有什么想法吗?

谢谢 拉克什

【问题讨论】:

抱歉,您能再解释一下您的问题吗?您是否定义了实体类但没有定义它们之间的关联?您可以发布您尝试过的代码吗?或许可以告诉我们您想要实现的目标。 没错,JPA 实体没有在 JPA 级别定义任何关系。编辑以包含示例代码。在给定的场景中,JPA 不提供外连接。原因:它需要符合 2/2.1 规范的对象路径。 那么为什么不使用关联“正确地”定义实体,让您的生活更轻松呢?定义这些实体之间的关系有什么缺点(除了你必须输入更多代码)? @DuncanKinnear 这是个好问题。定义 JPA 级别 OR 映射很大程度上取决于情况。当涉及到一个实体“组成”另一个实体的情况时,它们是救命稻草,即实体 1 仅在实体 2 存在时才存在。但是,在所有情况下都不是必须的。例如。审计就是这样一个例子。我宁愿避免 OR 映射本身而不是映射,然后处理延迟/急切加载和相关的休​​眠会话边界问题。 【参考方案1】:

您可以使用 theta 样式的连接来模拟 INNER JOIN:

    select c, o
    from Customer c, Order o
    where c.id= o.customerId

大多数现代数据库引擎查询优化器会将其变成INNER JOIN equivalent anyway。

【讨论】:

谢谢。从逻辑上讲,这应该有效。将测试并恢复。 我刚刚修改了 OP 中的实体定义。您能否建议修改您提到的 LEFT JOIN 查询?谢谢。 查询返回所有,即有订单和没有订单的客户。但需要的是没有订单的客户。 这就是 LEFT join 的工作原理。尝试为没有订单的客户提供 Dragan 答案。【参考方案2】:

假设您在 Order 实体中有 customerId 字段 (Integer)。为了找到没有订单的客户,可以使用子查询避免外连接和原生查询:

select c from Customer c where id not in (select customerId from Order)

这样您就可以在 JPQL (HQL) 中实现相同的目标。

【讨论】:

嗯,通常我们不会为了支持查询而添加列。在报告的情况下,客户已经有 orderId,在 Order 中有 customerId 是多余的,不是正确的方法。 只要按照建议定义关联,就可以正常工作 接受所需的答案。但是,我仍然会选择带有左外连接的本机查询以避免内部查询。谢谢。

以上是关于JPA 支持没有对象关系映射的外部连接的主要内容,如果未能解决你的问题,请参考以下文章

JPAHibernateSpring Data JPA 的关系,你懂吗?

JPAHibernateSpring data jpa之间的关系,终于明白了

JPAHibernateSpring data jpa之间的关系,终于明白了

JPA

JPA

JPA