采用与Spring数据JPA连接继承时,跨表避免外连接(Avoiding outer joins a

2019-09-03 01:59发布

考虑在Spring数据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();

每当调用此方法,下面的SQL查询的是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类,所以我觉得左外连接没用。

问题是,在我们的实际应用中,有8个孩子类,如EmployeeCustomer以及数百万条记录中的每个子表,这是造成父表的查询运行速度很慢。

有没有一种方法,以避免在这种情况下,外跨表的连接? 请注意,我用的尝试DiscriminatorColumn方法和联接在这种情况下仍然执行(当使用Hibernate时)。 我也曾尝试休眠特定的Polymorphism对实体类注释中的所有可能的组合和联接仍然执行外。

Spring Data JPA version: 1.2.0
Hibernate version: 4.2.1

Answer 1:

经过努力解决这个问题很多天,我得出以下结论:

  1. 有没有办法来强制Hibernate 4.x版(和3.x)不执行在这种情况下外部联接。
  2. 有没有办法强迫的TopLink要点(v2.1-60)和OpenJPA(V2.2.2)的最新可用版本不进行外部联接无论是。
  3. 这是可能避免的EclipseLink(V2.5.0)的最新版本的外部联接。 然而,需要的EclipseLink上面显示的类层次结构鉴别列,即使Hibernate和OpenJPA的没有。 到目前为止,我一直无法找到一个方法来避免同时使用的EclipseLink鉴别列。

我想我将不得不等待或者JPA规范来改变或JPA实现变得可用,满足我目前的需求。



Answer 2:

没有直接回答你的问题,但是:

您可以取代这种继承与@OneToOne组成。

表结构将保持几乎相同。 你可以查询具体类型,而这些连接要避免的。

@Entity
@Table(name = "personDetails")
public class PersonDetails { }

@Entity
@Table(name = "customer")
public class Customer {

   @OneToOne
   PersonDetails personDetails;
 }

@Entity
@Table(name = "employee")
public class Employee {

   @OneToOne
   PersonDetails personDetails;

 }

@Entity
@Table(name = "manager")
public class Manager {

   @OneToOne
   PersonDetails personDetails;

 }

只是改变了名字的人来PersonDetails有这方面的一个更好的名字。



文章来源: Avoiding outer joins across tables when using joined inheritance with Spring Data JPA