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

查看:17
本文介绍了在 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个子类,例如EmployeeCustomer,每个子表中有数百万条记录,导致查询父表运行很慢.

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:

  1. 在这种情况下,无法强制 Hibernate 4.x(和 3.x)不执行外连接.
  2. 也无法强制 TopLink Essentials (v2.1-60) 和 OpenJPA (v2.2.2) 的最新可用版本不执行外连接.
  3. 使用最新的 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屋!

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