获取所有属性是否会在幕后进行左连接?
Does fetch all properties do left join under the hood?
我的实体如下所示:为简化起见,我只显示了两个字段。我们决定执行 fetch all 以一次加载所有属性。
@Entity
public class Person{
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Set<PhoneNumber> phoneNumbers = new HashSet<>(0);
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "AGENCY_ID")
private Agency agency;
左连接:(此returns重复记录。)
select person
from Person person left join person.agency ag left join person.phoneNumbers
where upper(person.name) LIKE '%SU%' and upper(person.status.rcode) = 'ACTIVE'
order by person.agency.name asc, person.id asc
left join with distinct : 这给出了 "ORA-01791: not a SELECTed expression" 因为我在 order 子句中使用了 agency 字段。
select distinct person
from Person person left join person.agency ag left join person.phoneNumbers
where upper(person.name) LIKE '%SU%' and upper(person.Status.rcode) = 'ACTIVE'
order by person.agency.name asc, person.id asc
left join fetch:这很好用,没有重复。但对拉动 2000 人的记录有很大的影响。大约需要 15 秒,而左连接需要 1 秒。
select person
from Person person left join fetch person.agency ag left join fetch person.phoneNumbers
where upper(person.name) LIKE '%SU%' and upper(person.Status.rcode) = 'ACTIVE'
order by person.agency.name asc, person.id asc
获取所有属性:没有重复项。执行 better.But..
当我尝试查询如下人员时(此人没有任何代理):它 returns 人员记录(这意味着它正在进行左连接)。
select person
from Person person
fetch all properties
where upper(person.name) LIKE '%SU%' and upper(person.status) = 'ACTIVE'
order by person.id asc
但是当我执行以下操作时,我没有取回人员记录。 (不同的是在order by clause中添加了agency的字段,这里好像没有做left join)
select person
from Person person
fetch all properties
where upper(person.name) LIKE '%SU%' and upper(person.status) = 'ACTIVE'
order by person.agency.name asc, person.id asc
我要找的是避免重复,按所有领域表现好的人排序。
导航路径语法 (person.agency
) 总是被翻译成内部连接,这就是为什么没有代理的人不包含在结果集中。
您必须显式编写外连接以避免隐式内连接:
select person
from Person person left outer join person.agency a
where upper(person.name) LIKE '%SU%' and upper(person.status) = 'ACTIVE'
order by a.name asc, person.id asc
编辑
distinct
在 left join
情况下不起作用,因为按 select distinct
子句中提到的列中未包含的列排序没有意义。
如果你想在查询中急切加载惰性关联,那么你别无选择,只能这样做left join fetch
。但是也会返回重复项。要消除它们,只需将返回的列表添加到 LinkedHashSet
以保留返回的顺序:
List<Persons> result = new ArrayList(new LinkedHashSet(list))
关于这种方法的性能不好,Hibernate与它无关。您可能在左连接获取的实体中有一些急切加载的实体(因此遭受 n+1 选择问题),或者重复的实体非常大(因此制作和传输一个大的结果集)。
您可能希望使用 而不是左连接提取集合以避免性能问题。
我的实体如下所示:为简化起见,我只显示了两个字段。我们决定执行 fetch all 以一次加载所有属性。
@Entity
public class Person{
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Set<PhoneNumber> phoneNumbers = new HashSet<>(0);
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "AGENCY_ID")
private Agency agency;
左连接:(此returns重复记录。)
select person
from Person person left join person.agency ag left join person.phoneNumbers
where upper(person.name) LIKE '%SU%' and upper(person.status.rcode) = 'ACTIVE'
order by person.agency.name asc, person.id asc
left join with distinct : 这给出了 "ORA-01791: not a SELECTed expression" 因为我在 order 子句中使用了 agency 字段。
select distinct person
from Person person left join person.agency ag left join person.phoneNumbers
where upper(person.name) LIKE '%SU%' and upper(person.Status.rcode) = 'ACTIVE'
order by person.agency.name asc, person.id asc
left join fetch:这很好用,没有重复。但对拉动 2000 人的记录有很大的影响。大约需要 15 秒,而左连接需要 1 秒。
select person
from Person person left join fetch person.agency ag left join fetch person.phoneNumbers
where upper(person.name) LIKE '%SU%' and upper(person.Status.rcode) = 'ACTIVE'
order by person.agency.name asc, person.id asc
获取所有属性:没有重复项。执行 better.But.. 当我尝试查询如下人员时(此人没有任何代理):它 returns 人员记录(这意味着它正在进行左连接)。
select person
from Person person
fetch all properties
where upper(person.name) LIKE '%SU%' and upper(person.status) = 'ACTIVE'
order by person.id asc
但是当我执行以下操作时,我没有取回人员记录。 (不同的是在order by clause中添加了agency的字段,这里好像没有做left join)
select person
from Person person
fetch all properties
where upper(person.name) LIKE '%SU%' and upper(person.status) = 'ACTIVE'
order by person.agency.name asc, person.id asc
我要找的是避免重复,按所有领域表现好的人排序。
导航路径语法 (person.agency
) 总是被翻译成内部连接,这就是为什么没有代理的人不包含在结果集中。
您必须显式编写外连接以避免隐式内连接:
select person
from Person person left outer join person.agency a
where upper(person.name) LIKE '%SU%' and upper(person.status) = 'ACTIVE'
order by a.name asc, person.id asc
编辑
distinct
在 left join
情况下不起作用,因为按 select distinct
子句中提到的列中未包含的列排序没有意义。
如果你想在查询中急切加载惰性关联,那么你别无选择,只能这样做left join fetch
。但是也会返回重复项。要消除它们,只需将返回的列表添加到 LinkedHashSet
以保留返回的顺序:
List<Persons> result = new ArrayList(new LinkedHashSet(list))
关于这种方法的性能不好,Hibernate与它无关。您可能在左连接获取的实体中有一些急切加载的实体(因此遭受 n+1 选择问题),或者重复的实体非常大(因此制作和传输一个大的结果集)。
您可能希望使用