ewe*_*nli 7 database hibernate jpa hql
我们想在 HQL 中使用两列进行左外连接两个表的连接。
连接的第二列在逻辑级别没有相关性,并且不会以任何方式限制结果集。它是分区键,仅用作加速物理数据访问的优化。
在 SQL 中,它类似于
select *
from t1
left outer join t2
on t1.id = t2.parent_id
and t1.partion_key = t2.partition_key
Run Code Online (Sandbox Code Playgroud)
我们尝试的以下方法不起作用:
我们可以在 HQL 中进行外连接,left join fetch并且可以在连接中指定附加条件, with但两者不能结合在一起。文档中明确提到了此限制:“Fetch 也不应与即席条件一起使用”。
使用额外的 where 条件t1.partion_key = t2.partition_key不起作用,因为它将查询的语义从外连接更改为内连接:当没有数据匹配时,条件不成立并且行被忽略。
使用 oracle 语法t1.partion_key = t2.partition_key (+)也不起作用,因为它会导致 SQL 查询混合了 ANSI 和 Oracle 语法。
我们虽然考虑使用组合键,但它并不是真正正确的,因为在逻辑级别,键只是id. 我们不想让物理数据建模(分区)影响逻辑模型。
我们如何用 HQL 表达所需的查询?
1) 从 Hibernate 5.1 开始,我们可以在 HQL 查询中对不相关的类使用“join”。在这种情况下,我们可以使用这个 HQL 查询:
select
p as parent,
c as child
from
Parent p
left join Child c on c.parentId = p.id and c.partitionKey = p.partitionKey
Run Code Online (Sandbox Code Playgroud)
2)另一种方法是修改实体如下(在实体中的属性中添加两个JoinColumns并将“多对一”关系替换为实体中的简单属性):childrenParentparentparentIdChild
@Entity
public class Parent {
@Id
@GeneratedValue
private Integer id;
@Column(name = "partition_key")
private Integer partitionKey;
@OneToMany
@JoinColumns({
@JoinColumn(name = "parent_id", referencedColumnName = "id"),
@JoinColumn(name = "partition_key", referencedColumnName = "partition_key")
})
private List<Child> children;
}
@Entity
public class Child {
@Id
@GeneratedValue
private Integer id;
@Column(name = "partition_key")
private Integer partitionKey;
@Column(name = "parent_id")
private Integer parentId;
// @ManyToOne
// private Parent parent;
}
Run Code Online (Sandbox Code Playgroud)
然后我们可以使用以下简单的 JPQL 查询:
select distinct p as parent from Parent p left join fetch p.children c
Run Code Online (Sandbox Code Playgroud)
这两个查询都被 Hibernate 翻译成喜欢这个 SQL 查询:
select
p.id,
p.partition_key,
s.id,
s.parent_id,
s.partition_key
from
parents p
left outer join children c on (c.parent_id=p.id and c.partition_key=p.partition_key)
Run Code Online (Sandbox Code Playgroud)
工作演示在这里。
如果没有复合主键,很难在 Hibernate 中使用表分区,因此您实际上没有太多选择。
我想到的一件事是尝试仍然通过附加的 where 子句和 null 检查来实现外连接语义:
where t1.partion_key = t2.partition_key OR t2.partition_key is null
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7867 次 |
| 最近记录: |