【问题标题】:Hibernate Criteria to query more than one class (or restrict by a list of subclasses)Hibernate Criteria 查询多个类(或受子类列表限制)
【发布时间】:2015-03-04 19:56:08
【问题描述】:

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

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。

注意:我不知道我是否应该将此问题视为“查询多个类”(其中所有字段的名称与我正在查询的字段名称相同),或者我是否应将其视为“通过子类列表限制查询”。

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

【问题讨论】:

  • 你能写一个简单的 sql 来描述你想要什么考虑这些类作为表。
  • 对不起,我不知道怎么做。
  • 你能不能创建一个接口,“Criteriable”,只有那些你想应用标准来实现的类?那么 session.createCriteria(Criteriable.class) 呢?我从来没有试过这个,但它首先想到的是:)
  • 我不能,因为我需要的类在运行时一直在变化。
  • 您只想在 1 个命令中创建此条件?考虑到所有类都实现了 Operation,您可以为每个类创建一个条件,并将所有列表放在一起返回。

标签: java hibernate hibernate-criteria


【解决方案1】:

一般来说,Hibernate 对加入不相关实体的支持非常有限。 “不相关”是指没有相互引用的实体。 Critera API 根本不支持,HSQL 只能做交叉连接。不要误会,底层的 Criteria/HQL 实现能够连接不相关的实体,但 API 不公开此功能。 (您可以对相关实体进行各种连接(内、左、右、全)。) 对不相关实体进行内部/左/右/完全连接的唯一方法是本机 sql。 但是,如果不相关的实体有共同的父类,则可以使用称为“隐式多态性”的休眠功能:选择父类,将返回父类及其所有子类。然后您可以将结果限制为子类列表。
所以试试这个:

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

编辑:
下面是一个如何查询父类中不存在的属性的示例: 在此示例中,属性“f”和“value”不存在于 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();

【讨论】:

  • 好的,很好,我拥有的所有课程确实与共同的父母Operation.class相关。但是,它似乎只有在我查询 Operation 类本身中实际存在的某些字段时才有效。如果我查询所有子类中存在的某些字段(OpA2OpB1OpB3OpC)但不在 Operation 中,那么我会得到这个异常:MySQLSyntaxErrorException: Not unique table/alias
  • 参见编辑部分。
猜你喜欢
  • 2021-02-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-28
相关资源
最近更新 更多