小编典典

在Spring Data JPA中使用联接继承时,避免跨表进行外部联接

hibernate

在Spring Data JPA(+ Hibernate)应用程序中考虑以下类:

@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):

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 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类中的公共字段感兴趣,因此我发现左外部联接无用。

问题在于,在我们的实际应用程序中,每个子表中都有8个子类,例如Employee和和Customer以及数百万条记录,这导致父表上的查询运行非常慢。

在这种情况下,是否有办法避免跨表的外部联接?请注意,我已尝试使用该 DiscriminatorColumn
方法,并且在这种情况下(使用Hibernate时)仍会执行连接。我还尝试了 Polymorphism
在所有可能的组合中对实体类进行特定于Hibernate的注释,并且仍然执行外部联接。

Spring Data JPA version: 1.2.0
Hibernate version: 4.2.1

阅读 290

收藏
2020-06-20

共1个答案

小编典典

经过数天的尝试解决此问题,我得出以下结论:

  1. 在这种情况下,无法强制Hibernate 4.x(和3.x)不执行外部联接。
  2. 也无法强制TopLink Essentials(v2.1-60)和OpenJPA(v2.2.2)的最新可用版本也不执行外部联接。
  3. 可以避免使用最新的EclipseLink版本(v2.5.0)进行外部联接。但是,即使Hibernate和OpenJPA不需要,EclipseLink仍需要上面显示的类层次结构的discriminator列。到目前为止,我一直无法找到避免在EclipseLink中使用discriminator列的方法。

我想我将不得不等待JPA规范更改或满足我当前需求的JPA实现可用。

2020-06-20