Java 如何在Hibernate中执行非多态HQL查询?

Java 如何在Hibernate中执行非多态HQL查询?,java,hibernate,orm,Java,Hibernate,Orm,我使用的是Hibernate 3.1.1,尤其是HQL查询 根据,Hibernate的查询是多态的: 类似于:fromcatascat的查询不仅返回Cat的实例,还返回子类的实例,如DomesticCat 如何查询Cat实例,而不是其任何子类的实例? 我希望能够做到这一点,而不必显式地提到每个子类 我知道以下选项,但不满意: 在查询后手动筛选实例,或: 在鉴别器列上手动添加WHERE子句 Hibernate允许用户决定一个查询是否应该是多态的是有意义的,但是我找不到这样的选项 提前谢谢 SELE

我使用的是Hibernate 3.1.1,尤其是HQL查询

根据,Hibernate的查询是多态的:

类似于:
fromcatascat
的查询不仅返回
Cat
的实例,还返回子类的实例,如
DomesticCat

如何查询Cat实例,而不是其任何子类的实例?

我希望能够做到这一点,而不必显式地提到每个子类

我知道以下选项,但不满意:

  • 在查询后手动筛选实例,或:
  • 在鉴别器列上手动添加WHERE子句
  • Hibernate允许用户决定一个查询是否应该是多态的是有意义的,但是我找不到这样的选项

    提前谢谢

    SELECT cat FROM Cat cat WHERE cat.class='cat'
    
    其中值
    'cat'
    cat
    类的鉴别器值

    如果您使用的是
    TABLE\u PER\u CLASS
    ,请尝试
    cat.CLASS='cat'
    )(类的名称)


    这不完全是鉴别器列上的where子句,因为这样的查询将失败(鉴别器列仅在本机查询中可用)。

    ORM模仿Java模型:如果对象是另一种类型的实例(如果PersianCat的实例也是Cat的实例),则Cat上的任何查询都必须是多态的(假设您查询一个列表,并询问条目是否匹配Cat的
    instanceof

    即使是Bozho的解决方案也有点不纯,因为“class”列对于hibernate映射来说是不透明的,尽管我承认这是一个很好的折衷方案。您只需通过类的简单名称就可以得到鉴别器

    如果您感到舒适,并且每个类使用,则始终可以对Cat表执行本机查询以获取ID,然后通过hibernate获取条目。

    在中使用
    polymorphic=“explicit”
    。这将导致查询只返回命名类的实例,而不返回其子类

    隐式多态性意味着 该类的实例将是 由命名任何 超类或实现的接口或 类,以及任何 将返回该类的子类 通过命名类的查询 显式多态性意味着 将返回该类实例 仅通过显式命名的查询 那个班


    查看BaseQueryReturnFieldScalCalculatorgC;它动态地向“where”添加一个条件,该条件仅选择where class=XXX;您可以将此逻辑复制到HQLQueryTemplate,并让用户定义“isNonPolymorphic”

    请注意,它只适用于每个层次结构的表,因为只有这样隐式类列才存在并且是可选的。

    JPA 2(Hibernate 3.5)添加了对非多态查询的支持,这与Hibernates.class属性非常相似(如Bozho上面回答的)但它不是特定于Hibernate的。这是使用类型运算符完成的

    Select b from Book b where TYPE(b) = Book
    
    你可以在我的博客上读到更多


    Eyal

    谢谢,但我试图避免编辑WHERE子句。如果我同意你的建议,Hibernate将在WHERE中添加自己的部分,结果将是“WHERE c.class='cat'和c.class'IN('cat','domesticCat')”。我宁愿有一种方法告诉查询一次性“关闭”其多态功能(如果存在这种情况的话)。为什么不指定where子句?因为我有一段对不同实体执行不同查询的通用框架代码。我希望能够将配置参数传递给通用代码,以便在多态和非多态模式之间切换。如果必须,通用代码将修改where子句,但这将需要查找鉴别器值(尽管这并不困难),并且可能会导致where子句中出现不必要的部分(参见我之前的评论).没错,99%的时候你应该像对待基类的任何其他实例一样对待子类的实例-就像在Java中使用
    x instanceof Cat
    一样。但是,我的问题是关于另外1%的问题,当你有理由不想加载子类时-就像使用
    x.getClass()==Cat.class
    在Java中。在我的情况下,这是在系统引导期间,我还不能实例化子类型对象。你能分享你的设计吗?通常情况下,当事情如此困难时,设计可能会有缺陷或更好的处理方式。太棒了!在我的情况下,我需要它基于每个查询,而不是每个实体,但我认为我需要它有一种方法可以做到这一点——在我的
    EntityPersister
    上重写
    isExplicitPolymorphism
    方法。你肯定给了我一个正确的方向。我最近从Hibernate 4.1.3升级到了Java 8所需的4.3.5。我的非多态查询现在被破坏了:Hibernate生成的SQL完全错误。在4.1.3中,它是alr已经在where子句中做了一些奇怪的切换/case,但现在它只是不正确:没有引用鉴别器列值(字符串):“…where case when patient0_1_.id不为null那么a when patient0_.id不为null那么‘P’end‘a’…”我的截肢者类扩展了Patient,带有Patient鉴别器‘P’和截肢者‘a’。在“then a”中,它忽略了引用A,从而生成了无效的SQL。请参阅我对此问题的扩展:它可能缺少“=”运算符。Try:TYPE(b)=Book