在 Spring Data JPA 中使用连接继承时避免跨表外连接 [英] Avoiding outer joins across tables when using joined inheritance with Spring Data JPA
问题描述
在 Spring Data JPA (+ Hibernate) 应用程序中考虑以下类:
Consider the following classes in a Spring Data JPA (+ Hibernate) application:
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@Table(name = "person")
public class Person { }
@Entity
@Table(name = "customer")
public class Customer extends Person { }
@Entity
@Table(name = "employee")
public class Employee extends Person { }
@Entity
@Table(name = "manager")
public class Manager extends Employee { }
public interface IPersonRepository extends JpaRepository<Person, Long> { }
public interface ICustomerRepository extends JpaRepository<Customer, Long> { }
public interface IEmployeeRepository extends JpaRepository<Employee, Long> { }
我最常见的用例涉及调用以下方法(继承自 JpaRepository
):
My most common use case involves calling the following method (inherited from JpaRepository
):
IPersonRepository.findAll();
每当调用此方法时,Hibernate 都会发出以下 SQL 查询:
Whenever this method is invoked, the following SQL query is issued by Hibernate:
select
person0_.id as id1_3_,
person0_.version as version2_3_,
person0_.first_name as first3_3_,
person0_.last_name as last4_3_,
person0_1_.customer_code as customer1_0_,
person0_2_.employee_code as employee1_1_,
person0_2_.manager_id as manager3_1_,
case
when person0_3_.id is not null then 3
when person0_1_.id is not null then 1
when person0_2_.id is not null then 2
when person0_.id is not null then 0
end as clazz_
from
person person0_
left outer join
customer person0_1_
on person0_.id=person0_1_.id
left outer join
employee person0_2_
on person0_.id=person0_2_.id
left outer join
manager person0_3_
on person0_.id=person0_3_.id;
每当执行此查询时,我只对 Person
类中的公共字段感兴趣,所以我发现左外连接没用.
Whenever this query is executed, I am interested only in the common fields in the Person
class, so I find the left outer joins useless.
问题是在我们的实际应用中,有8个子类,例如Employee
和Customer
,每个子表中有数百万条记录,导致查询父表运行很慢.
The problem is that in our actual application, there are 8 child classes like Employee
and Customer
and millions of records in each child table, which are causing the query on the parent table to run very slow.
在这种情况下,有没有办法避免跨表的外连接?请注意,我已尝试使用 DiscriminatorColumn
方法,并且在这种情况下仍会执行连接(使用 Hibernate 时).我还在所有可能的组合中的实体类上尝试了特定于 Hibernate 的 Polymorphism
注释,并且仍然执行外部联接.
Is there a way to avoid the outer joins across the tables in this case? Please note that I have tried using the DiscriminatorColumn
approach and the joins are still performed in that case (when using Hibernate). I have also tried the Hibernate-specific Polymorphism
annotation on the entity classes in all possible combinations and still the outer joins are performed.
Spring Data JPA version: 1.2.0
Hibernate version: 4.2.1
推荐答案
经过多日的尝试解决这个问题,我得出以下结论:
After many days of trying to solve this problem, I have come to the following conclusion:
- 在这种情况下,无法强制 Hibernate 4.x(和 3.x)不执行外连接.
- 也无法强制 TopLink Essentials (v2.1-60) 和 OpenJPA (v2.2.2) 的最新可用版本不执行外连接.
- 使用最新的 EclipseLink (v2.5.0) 版本可以避免外连接.但是,EclipseLink 需要用于上面显示的类层次结构的鉴别器列,即使 Hibernate 和 OpenJPA 不需要.到目前为止,我一直无法找到避免在 EclipseLink 中使用鉴别器列的方法.
我想我将不得不等待 JPA 规范更改或满足我当前要求的 JPA 实现可用.
I guess I will have to wait for either the JPA specification to change or a JPA implementation to become available that satisfies my current requirement.
这篇关于在 Spring Data JPA 中使用连接继承时避免跨表外连接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!