与Spring Data JPA一起使用连接继承时,避免跨表的外连接 [英] Avoiding outer joins across tables when using joined inheritance with Spring Data JPA
问题描述
@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)
公共类管理器扩展Employee {}
公共接口IPersonRepository扩展JpaRepository< Person,Long> {}
公共接口ICustomerRepository扩展了JpaRepository< Customer,Long> {}
公共接口IEmployeeRepository扩展JpaRepository< Employee,Long> {}
我最常见的用例包括调用以下方法(从 JpaRepository
):
IPersonRepository.findAll();
无论何时调用此方法,Hibernate都会发出以下SQL查询:
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不为空然后3
当person0_1_.id不为空然后1
当person0_2_.id不为空然后2
当person0_.id不为空然后0
结束为clazz_
from
person person0_
left outer join
customer person0_1_
关于person0_.id = person0_1_.id
离开外部连接
员工person0_2_
对person0_.id = person0_2_.id
离开外部连接
经理person0_3_
对person0_.id = person0_3_.id;
每当执行此查询时,我只对 Person
class,所以我发现左外连接没用。
问题是在我们的实际应用程序中,有8个子类 Employee
和 Customer
以及每个子表中的数百万条记录,这些记录导致父表上的查询运行得非常慢。
在这种情况下,有没有办法避免表中的外连接?请注意,我尝试过使用 DiscriminatorColumn
方法,并且在这种情况下(使用Hibernate时)仍然执行连接。我也在所有可能的组合中尝试了Hibernate特有的 Polymorphism
注解,并且仍然执行外部连接。
Spring数据JPA版本:1.2.0
Hibernate版本:4.2.1
经过多天的试图解决这个问题,我得出以下结论: b
$ b
- 在这种情况下,无法强制Hibernate 4.x(和3.x)不执行外连接。
- 无法强制TopLink Essentials(v2.1-60)和OpenJPA(v2.2.2)的最新可用版本不执行外连接。
- 可以避免使用最新版本的EclipseLink(v2.5.0)进行外部连接。但是,即使Hibernate和OpenJPA不需要,EclipseLink也需要上述类层次结构的鉴别器列。到目前为止,我一直无法找到避免在EclipseLink中使用歧义列的方法。
我想我必须等待要么更改JPA规范,要么JPA实现可以满足我当前的要求。
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> { }
My most common use case involves calling the following method (inherited from JpaRepository
):
IPersonRepository.findAll();
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;
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.
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.
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:
- There is no way to force Hibernate 4.x (and 3.x) to not perform the outer joins in this case.
- There is no way to force the latest available versions of TopLink Essentials (v2.1-60) and OpenJPA (v2.2.2) to not perform the outer joins either.
- It is possible to avoid the outer joins with the latest available version of EclipseLink (v2.5.0). However, EclipseLink requires a discriminator column for the class hierarchy shown above, even though Hibernate and OpenJPA do not. So far I have been unable to find a way to avoid using the discriminator column with EclipseLink.
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屋!