具有具体类特定属性条件的多态 HQL 查询;可以吗?

Posted

技术标签:

【中文标题】具有具体类特定属性条件的多态 HQL 查询;可以吗?【英文标题】:polymorphic HQL queries with conditions on concrete-class-specific properties; can it be done? 【发布时间】:2011-12-13 20:45:30 【问题描述】:

我有一个映射到 hibernate 的类层次结构,看起来像这样:

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class Item  @ManyToOne Common common; ... 

@Entity
public class AbcItem extends Item  @ManyToOne Abc abc; ... 

@Entity
public class XyzItem extends Item  @ManyToOne Xyz xyz; ... 

也就是说,几个具体类共享一些关联,但每个类也有额外的单独关联。 (由于我使用的是单个表,因此类不使用的列只是 NULL。)

我想要的是能够用 HQL 查询混合具体类的项目列表,但是带有 where 子句,根据具体的类,将条件放在不常见的属性。类似“获取所有具有 i.common = 7 的 Items i,但如果它们是 AbcItems,它们必须具有 abc = 5”。

from Item查询所有项目很容易,我知道我可以用.class得到具体的类。但我想不出一种访问非公共属性或关联的方法。尝试from Item i where (i.class = AbcItem and i.abc = 5) or (i.class = XyzItem and i.xyz = 7) 会导致Hibernate 抱怨Item 没有abcxyz,这是真的。基本上,HQL 似乎有一个instanceof,但没有演员表。

我错过了什么吗?

(注意:我正在尝试在 HQL 中执行此操作 — ,如果可能的话,甚至使用 Criteria 查询 — 而不是原生 SQL,以在一定程度上独立于特定的数据库引擎。我知道如何使用原生 SQL 来做到这一点,所以不要不用费心去那里。

另外,我需要使用 one 查询来执行此操作。我知道我可以对每个类进行单独的查询并合并结果。这样做的问题在于,应用程序需要对“合并”结果进行分页,并按公共属性排序。用单独的查询来做这意味着加载大量不必要的项目,合并列表,对它们进行排序,然后丢弃大部分。我能想到的最佳算法要求,对于第 N 页,为每个子查询加载前 N 个页面。)

【问题讨论】:

如果您有“and i.abc.id = 5”而不是“and i.abc = 5”,那么您显示的查询就可以了。您能否发布异常的堆栈跟踪,因为我过去曾使用过此类查询(至少是条件查询)并且它们按原样工作。 嘿,这确实有效!谢谢你,@jb-nizet!生成的 SQL 查询对于 mysql 来说太糟糕了,无法优化(请参阅下面我对 Pablo 的回答,也许你有更好的主意),但这可能会在以后派上用场。 【参考方案1】:

如果“id”是主键:

from Item i
where (
   i.id in (select i2.id from AbcItem i2 where i2.abc = 5)
   or i.id in (select id2.id from XyzItem i2 where i2.xyz = 7)
   )
and ...
order by ...

【讨论】:

不幸的是,生成的 SQL 对 Item 表进行了全面扫描。在本机 SQL 中,我联合了子选择并使用 Item 加入了临时表;我可以直接在联合结果上执行 ORDER BY / LIMIT ,它只扫描页面大小的临时表。 HQL 似乎没有 UNION 之类的东西。对使用 HQL 做类似的事情有什么想法吗?

以上是关于具有具体类特定属性条件的多态 HQL 查询;可以吗?的主要内容,如果未能解决你的问题,请参考以下文章

多个类型/类的HQL查询

无法使用多态性访问具体类的唯一属性

HQL属性查询条件查询

Hibernate之HQL基本用法

hibernate用HQL查询集合属性

HQL实用技术(有待整改)