我正在使用Hibernate 3.1.1,特别是我正在使用HQL查询。
根据documentation,Hibernate的查询是多态的:
像
from Cat as cat
这样的查询不仅返回Cat
的实例,还返回DomesticCat
等子类的实例。
如何查询Cat的实例,而不查询其任何子类的实例?
我希望能够在不必明确提及每个子类的情况下完成它。
我知道以下选项,但发现它们并不令人满意:
让Hibernate允许用户决定查询是否应该是多态的,这是有意义的,但我找不到这样的选项。
提前致谢!
答案 0 :(得分:25)
在class mapping中使用polymorphism="explicit"
。这将导致查询仅返回指定类的实例而不返回其子类。
隐含多态意味着 班级的实例将是 由任何命名的查询返回 超类或实现的接口或 类,以及任何实例 将返回该类的子类 通过命名该类的查询 本身。显式多态意味着 将返回该类实例 仅通过明确命名的查询 那个班。
答案 1 :(得分:15)
SELECT cat FROM Cat cat WHERE cat.class='cat'
其中值'cat'
是Cat
类的鉴别值。
如果您使用TABLE_PER_CLASS
,请尝试cat.class='Cat'
)(班级名称)
这不是完全在discriminator列上的where子句,因为这样的查询将失败(鉴别器列仅在本机查询中可用)。
答案 2 :(得分:11)
JPA 2(Hibernate 3.5)增加了对非多态查询的支持,这与Hibernates .class属性非常相似(如上面的Bozho所述),但它不是特定于Hibernate的。这是使用TYPE运算符完成的。如在
Select b from Book b where TYPE(b) = Book
您可以在我的博客中详细了解here
的Eyal
答案 3 :(得分:1)
ORM模仿Java模型:如果一个对象是另一个类型的实例(如果PersianCat的实例也是Cat的一个实例),对Cat的任何查询都必须是多态的(想象一下你查询一个List并询问如果条目与instanceof Cat
匹配。
即使是Bozho的解决方案也有点不纯,因为“类”列对于你的hibernate映射是不透明的,尽管我承认它是一个非常好的折衷方案。你可以通过classe的简单名称来获得鉴别器。
如果你很舒服并且正在使用每个类的表,你可以随时对Cat表进行本机查询以获取ID,然后通过hibernate获取条目
答案 4 :(得分:0)
查看BaseQueryReturnFieldsCalculatorGC;它动态地为'where'添加一个条件,它只选择class = XXX;您可以将此逻辑复制到HQLQueryTemplate并让用户定义'isNonPolymorphic'。
请注意,它只适用于每个层次的表,只有那时隐式类列才存在且可以选择。