考虑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时)。我还在所有可能的组合中对实体类尝试了特定于Hibernate的 Polymorphism
注释,但仍然执行外连接。
Spring Data JPA version: 1.2.0
Hibernate version: 4.2.1
答案 0 :(得分:3)
经过多天尝试解决这个问题,我得出以下结论:
我想我将不得不等待更改JPA规范或提供满足我当前要求的JPA实现。
答案 1 :(得分:1)
不是您问题的直接答案,但是:
您可以使用@OneToOne合成替换此继承。
表结构将保持不变。您可以在没有要避免的JOIN的情况下查询具体类型。
@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;
}
刚刚将Person的名称更改为PersonDetails,以便在此上下文中有更好的名称。