假设我有一些类,如下所示:
OpA extends Operation
OpA1 extends OpA
OpA2 extends OpA
OpB extends Operation
OpB1 extends OpB
OpB2 extends OpB
OpB3 extends OpB
OpC extends Operation
Operation
|
/-----------------------------\
/ | \
OpA OpB OpC
/ |
/ |
/------\ /-----------\
/ \ / | \
OpA1 OpA2 OpB1 OpB2 OpB3
如果我想找一些操作,我可以这样做:
session.createCriteria(Operation.class)
.add(...)
.add(...)
.addOrder(...)
.setFirstResult(...)
.setMaxResults(...)
.list();
但是,如果我想将这些条件不应用于Operation.class
类型的所有操作,而只应用于类型类型的操作:OpA2
+ OpB1
+ OpB3
+ { {1}}?
我的问题:我怎样才能使用Hibernate Criteria?请不要HQL。
注意:我不知道我是否应该将此问题视为"查询多个班级" (其中所有字段都具有与我查询的字段相同的字段),或者如果我将其视为"通过子类列表限制查询"。
修改:如果我可以创建界面OpC
,然后创建课程TheOnesIWant
,OpA2
,OpB1
和{{1}实现这个接口,这将产生我想要的结果:OpB3
但是我不能这样做,因为我只知道我想在运行时查询的类。上面的类层次结构只是一个例子。
答案 0 :(得分:7)
通常,Hibernate对加入无关实体的支持非常有限。由"无关"我的意思是没有相互引用的实体。 Critera API根本不支持它,HSQL只能交叉连接。不要误解我,底层的Criteria / HQL实现能够加入不相关的实体,但API不会暴露这个功能。 (您可以在相关实体上执行各种连接(内部,左侧,右侧,完整)。)
在不相关的实体上进行内/左/右/完全连接的唯一方法是本机sql。
但是,如果不相关的实体具有共同的父级,则可以使用名为"隐式多态的"的hibernate功能:选择父级,将返回父级及其所有子类。然后,您可以将结果限制为子类列表。
所以试试这个:
List<Operation> list = session.createCriteria(Operation.class)
.add(Restrictions.or(
Property.forName("class").eq(OpA2.class)
,Property.forName("class").eq(OpB1.class)
,Property.forName("class").eq(OpB3.class)
,Property.forName("class").eq(OpC.class)))
.list();
修改强>
以下是如何查询父类中不存在的属性的示例:
在这个例子中,属性&#34; f&#34;和&#34;价值&#34;不存在于Operation类中,它们只存在于OpA2 abd OpC类中。
List<Operation> list = session.createCriteria(Operation.class)
.add(Restrictions.or(
Restrictions.and(Property.forName("class").eq(OpA2.class), Restrictions.eq("f", 1))
, Property.forName("class").eq(OpB1.class)
, Property.forName("class").eq(OpB3.class)
, Restrictions.and(Property.forName("class").eq(OpC.class), Restrictions.eq("value", "b"))))
.list();