Hibernate Criteria 查询多个 class (或受子 class 列表限制)

Hibernate Criteria to query more than one class (or restrict by a list of subclasses)

假设我有一些 classes,像这样:

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 + OpC?

我的问题:如何仅使用 Hibernate Criteria 来做到这一点?没有 HQL,请。

注意:我不知道是否应该将此问题视为 "querying more than one class"(其中所有字段的名称都与我正在查询的字段同名),或者我是否应将其视为 "restricting a query by a list of subclasses".

编辑: 如果我可以创建一个接口 TheOnesIWant,然后制作 classes OpA2OpB1OpB3OpC 实现了这个接口,这会产生我想要的结果: session.createCriteria(TheOnesIWant.class) 但是我不能这样做,因为我只知道我想要的 classes在 运行时 查询。上面的 class 层次结构只是一个例子。

一般来说,Hibernate 对加入不相关 实体的支持非常有限。 "unrelated" 我的意思是没有相互引用的实体。 Critera API 完全不支持,HSQL只能做cross join。不要误会我的意思,底层 Criteria/HQL 实现能够加入不相关的实体,但 API 不公开此功能。 (您可以对相关实体进行各种类型的连接(内连接、左连接、右连接、全连接)。) inner/left/right/full 加入不相关实体的唯一方法是原生 sql。 但是,如果不相关的实体有共同的父实体,您可以使用称为 "implicit polymorphism" 的休眠功能:选择父实体,将 return 父实体及其所有子 class 实体。然后您可以将结果限制为 sub-classes 的列表。
所以试试这个:

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();

编辑:
下面是一个如何查询父 class 中不存在的属性的示例: 在此示例中,属性 "f" 和 "value" 不存在于操作 class 中,它们仅存在于 OpA2 abd OpC classes.

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();