条件 API 未生成左外连接
Criteria API is not generating left outer join
我有 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 子句设置为 null,正如少数答案所建议的那样,但它被忽略了,因为 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 上发现了一个相关的错误。但是,不确定是不是这样。
我看到每个连接都重复两次,甚至连接别名也总是引用 SystemRules。可能是orderby导致了重复的inner join,我们可能需要明确的使用Join对象来引用extended column。
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))));
我有 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 子句设置为 null,正如少数答案所建议的那样,但它被忽略了,因为 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 上发现了一个相关的错误。但是,不确定是不是这样。
我看到每个连接都重复两次,甚至连接别名也总是引用 SystemRules。可能是orderby导致了重复的inner join,我们可能需要明确的使用Join对象来引用extended column。
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))));