0

当使用每类表策略时,多态查询如下所示:

SELECT <some cols> 
FROM 
  (
    SELECT 
      parent_id,
      entity1_col,
      entity2_col,
      1 as clazz_ 
    FROM 
      entity_table1 
    UNION 
    SELECT 
      parent_id,
      entity1_col,
      entity2_col,
      2 as clazz_ 
    FROM 
      entity_table2 
  ) abstract_entity 
WHERE 
  abstract_entity.parent_id = X

我们可以看到,如果 entity_table1 和 entity_table2 中有很多行,则此查询可能会导致性能问题。

我正在使用 Spring-data & Hibernate,并且在获取父实体上的 OneToMany 关系时会生成此请求。

我的问题是:为什么 Hibernate 会生成这样的请求,尽管它限制了 entity_table1 和 entity_table2 共有的 parent_id 上的选定行?

有没有办法让 Hibernate 生成如下所示的 SQL 请求:

SELECT <some cols>
FROM 
  (
    SELECT 
      parent_id,
      entity1_col,
      entity2_col,
      1 as clazz_ 
    FROM 
      entity_table1 
    WHERE 
      parent_id=X
    UNION 
    SELECT 
      parent_id,
      entity1_col,
      entity2_col,
      2 as clazz_ 
    FROM 
      entity_table2 
    WHERE 
      parent_id=X
  ) abstract_entity 

在 FROM 的每个请求中都有“WHERE parent_id=X”?这样在获取父实体上的关系时不会出现性能问题。

谢谢 !

4

1 回答 1

0

我在 hibernate 5.6.3 的基础上进行了修改,以在使用 table-per-concrete-class 策略时下推多态查询的预测。请参考https://github.com/kerler/hibernate-orm/tree/main_5.6.3-open-care

修改后代码“Query q = s.createQuery("from Being h where h.identity = :name1 or h.identity = :name2 or h.identity = :name2");” 在hibernate UT案例UnionSubclassTest.java::testNestedUnionedSubclasses()中,hibernate生成的SQL是这样的:

00:37:43,945 DEBUG SQL:144 - 
    select
        being0_.bid as bid1_2_,
        being0_.ident as ident2_2_,
        being0_.location as location3_2_,
        being0_.sex as sex1_6_,
        being0_.salary as salary1_4_,
        being0_.species as species1_0_,
        being0_.hive as hive2_0_,
        being0_.clazz_ as clazz_ 
    from
        ( select
            bid,
            ident,
            location,
            sex,
            salary,
            null as species,
            null as hive,
            2 as clazz_ 
        from
            employees 
        where
            ident=? 
            or ident=? 
            or ident=? 
        union
        all select
            bid,
            ident,
            location,
            sex,
            null as salary,
            null as species,
            null as hive,
            1 as clazz_ 
        from
            humans 
        where
            ident=? 
            or ident=? 
            or ident=? 
        union
        all select
            bid,
            ident,
            location,
            null as sex,
            null as salary,
            species,
            hive,
            3 as clazz_ 
        from
            aliens 
        where
            ident=? 
            or ident=? 
            or ident=? 
    ) being0_ 
where
    being0_.ident=? 
    or being0_.ident=? 
    or being0_.ident=?
于 2022-01-06T01:52:38.603 回答