对父类的休眠查询创建无效的联合查询

时间:2018-11-27 13:43:36

标签: java spring hibernate spring-boot spring-data-jpa

我正在使用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_ ....

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

1 个答案:

答案 0 :(得分:1)

如果您想在多态查询中获得最佳性能,最好的方法是使用strategy = InheritanceType.SINGLE_TABLE,那么您可能会为空列支付性能,但这取决于哪个方面对您更重要,这也是因为{{1 }}的问题与strategy = InheritanceType.JOINED