我的实体如下所示:简化我只是显示两个字段。我们决定一次性获取所有属性。
@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;
左连接:(这会返回重复的记录。)
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
左连接与distinct:这给出了“ORA-01791:不是SELECTed表达式”,因为我在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
左连接提取:这很好,没有重复。但是在拉动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
获取所有属性:无重复项。表现更好。但.. 当我尝试查询下面这样的人时(这个人没有任何代理):它返回人员记录(这意味着它正在进行左连接)。
select person
from Person person
fetch all properties
where upper(person.name) LIKE '%SU%' and upper(person.status) = 'ACTIVE'
order by person.id asc
但是当我在下面做的时候,我不会把这个人记录下来。 (差异是按顺序添加代理的字段,在这种情况下似乎没有做左连接。)
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
我所期待的是避免重复,可以对所有表现良好的人进行排序。
答案 0 :(得分:1)
导航路径语法(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选择问题),或者复制的实体非常大(从而制作和传输大型结果集)。
您可能希望使用@BatchSize
而不是left-join-fetching集合来避免性能问题。