对父类进行Hibernate查询会产生无效的联合查询

问题描述 投票:0回答:1

我正在使用spring boot和hibernate,我有以下数据结构。

@Entity
public class Template {

  @Id
  private Integer id;

  @OneToMany(mappedBy = "template", orphanRemoval = true, fetch = FetchType.EAGER,cascade = CascadeType.ALL)
  @BatchSize(size = 30)
  private Collection<TemplateContent> contents;
}

@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class TemplateContent {

  @Id
  private String contentType;

  @Id
  @ManyToOne(fetch = FetchType.EAGER, optional = false)
  @JoinColumn(name = "template_id", nullable = false)
  private Template template;
}

@Entity
public class SomeContent extends TemplateContent {

   private String someValue;
}

@Entity
public class SomeOtherContent extends TemplateContent {

   private String someOtherValue;
}

@Repository
public interface TemplateRepository extends JpaRepository<Template, Integer> {
  Page<Template> findByIdIn(Collection<Integer> ids, Pageable pageable);
}

当我调用findByIdIn方法时,它会生成以下查询:

SELECT ...
FROM   (SELECT content_type, 
               template_id, 
               some_value, 
               NULL AS some_other_value
        FROM   someContent
        UNION 
    SELECT content_type, 
               template_id, 
               some_other_value, 
               NULL AS some_value
        FROM   someOtherContent) contents0_ 
WHERE  contents0_.template_id IN ( ?, ?, ? ) 

这是无效的,因为MySQL不能使用索引而不是派生表。有没有办法生成更有效的查询。

//this would be the desired query
SELECT ...
FROM   (SELECT content_type, 
               template_id, 
               some_value, 
               NULL AS some_other_value
        FROM   someContent
        WHERE template_id IN ( ?, ?, ? )
        UNION 
    SELECT content_type, 
               template_id, 
               some_other_value, 
               NULL AS some_value
        FROM   someOtherContent
        WHERE template_id IN ( ?, ?, ? )) contents_0_ ....

我也尝试使用不同的继承策略,但似乎所有这些都有类似的缺点。

java spring hibernate spring-boot spring-data-jpa
1个回答
1
投票

如果你想在多态查询中获得最佳性能,最好的方法是使用strategy = InheritanceType.SINGLE_TABLE,可能你会用空列支付性能,但它取决于哪个方面对你更重要,也因为strategy = InheritanceType.JOINED有同样的问题TABLE_PER_CLASS

© www.soinside.com 2019 - 2024. All rights reserved.