【问题标题】:Criteria API is not generating left outer join标准 API 未生成左外连接
【发布时间】:2017-08-19 00:20:06
【问题描述】:

我有 3 个实体,事实上,为了简洁起见,更多的实体结合在一起,我正在跳过这些实体,我正在使用 open jpa 2.2.2 和 oracle 11g。有什么想法吗?

Entity SystemRules{
@OneToMany(mappedBy = "systemRule", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    private List<ServiceActionMap> serviceActionMap;
}

Entity ServiceActionMap{
    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "SYSTEM_RULE_ID")
    private SystemRules systemRule;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "RFS_TYPE_ID", nullable = true)
    private RfsTypeMap rfsType;
}

Entity RfsTypeMap{
    @Id
    @Column(name="RFS_TYPE_ID" ,nullable=false)
    private BigDecimal rfsTypeId;

    @Column(name="RFS_NAME")
    private String rfsName;
}

现在,我正在尝试按 RfsTypeMap.rfsName 对结果进行排序,我正在使用标准生成器以下列方式创建查询

CriteriaQuery<SystemRules> query = cb.createQuery(SystemRules.class);
Root<SystemRules> root= query.from(SystemRules.class);
root.fetch(SystemRules_.serviceActionMap).fetch(ServiceActionMap_.rfsType, JoinType.LEFT);

我的order by子句是这样的

cb.desc(cb.upper(systemRules.get("serviceActionMap").get("rfsType").get("rfsName").as(String.class)));

生成 JPQL 看起来像,我希望 ServiceActionMap 和 RfsTypeMap 之间有一个左外连接子句,但它丢失了。同样在 SQL 中被翻译,我错过了那些 ServiceActionMap.rfsType 为空值的记录。

SELECT  DISTINCT s FROM SystemRules s INNER JOIN FETCH s.serviceActionMap  INNER JOIN FETCH s.serviceActionMap  INNER JOIN FETCH s.ruleProperty  INNER JOIN FETCH s.ruleProperty where ... ORDER BY UPPER(s.serviceActionMap.rfsType.rfsName)

我在这里尝试过几个答案,但没有成功,尝试明确放置 ServiceActionMap.rfsType 的 where 子句,正如少数答案所建议的那样,但它被忽略了,因为 join 发生在 where 评估之前。这个问题openJPA outer join on optional many-to-one when have order by clause 与我的场景相匹配,但无法通过标准 API 生成建议的 JPQL。

我在 apache jira https://issues.apache.org/jira/browse/OPENJPA-2318 上发现了一个相关的错误。但是,不确定情况是否如此。

【问题讨论】:

  • 无法保证会使用 FETCH 连接,因为它只是用来获取的,而 JPA 提供者完全有权在附加的 SQL 调用中执行此操作(因为通常以某种方式神奇地获取每个可能的字段都会导致过于复杂的 SQL)。如果它是一个没有 fetch 的 JOIN,那么它应该使用它
  • 即使有连接,也不总是在这两个表之间使用左连接。为什么不总是这样,因为在某些情况下,当我同时使用 fetch 和 join 时(比如 table a join a.b 和 table a fetch a.c),它正确使用了 a & b 之间的左连接和 a & c 之间的内连接。但是当我尝试(表 a 连接 a.b 和表 a 连接 a.c)时,它遵循所有 3 个表 a、b 和 c 之间的内部连接。连接列的排序效果很好(左连接的结果),但右侧表的其他属性不行(它总是产生内连接)。

标签: java jpa left-join openjpa


【解决方案1】:

我看到每个连接都重复了两次,甚至连接别名也总是引用 SystemRules。可能是 orderby 导致了重复的内连接,我们可能需要显式使用 Join 对象来引用扩展列。

CriteriaQuery<SystemRules> query = cb.createQuery(SystemRules.class);
Root<SystemRules> root = query.from(SystemRules.class);
Join<SystemRules, ServiceActionMap> join1 = root.join(SystemRules_.serviceActionMap, JoinType.INNER);
Join<ServiceActionMap, RfsTypeMap> join2 = join1.join(ServiceActionMap_.rfsType, JoinType.LEFT);
query.orderBy(cb.desc(cb.upper(join2.get(RfsTypeMap_.rfsName))));

【讨论】:

  • 我没有得到这部分。 Join&lt;ServiceActionMap, RfsTypeMap&gt; join2 = join1.join(SRfsTypeMap_.rfsType, JoinType.LEFT); SRfsTypeMap_ 是 RfsTypeMap 的元模型类吗?如果是,那么它将不允许我加入来自 RfsTypeMap_.rfsTypeId 的字段。下面是我的元模型类。 public class RfsTypeMap_ { public static volatile SingularAttribute&lt;RfsTypeMap, BigDecimal&gt; rfsTypeId; public static volatile SingularAttribute&lt;RfsTypeMap, String&gt; rfsName;
  • 啊..我的错。它应该是 ServiceActionMap 元模型。更正了。
猜你喜欢
  • 2013-09-05
  • 2012-02-02
  • 1970-01-01
  • 1970-01-01
  • 2014-04-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多