与Spring Data JPA一起使用连接继承时,避免跨表的外连接 [英] Avoiding outer joins across tables when using joined inheritance with Spring Data JPA

查看:402
本文介绍了与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


  1. 在这种情况下,无法强制Hibernate 4.x(和3.x)不执行外连接。
  2. 无法强制TopLink Essentials(v2.1-60)和OpenJPA(v2.2.2)的最新可用版本不执行外连接。

  3. 可以避免使用最新版本的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:

  1. There is no way to force Hibernate 4.x (and 3.x) to not perform the outer joins in this case.
  2. 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.
  3. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆