【问题标题】:Hibernate criteria with restrictions on children具有对儿童限制的休眠标准
【发布时间】:2011-10-23 15:34:59
【问题描述】:

我有一个 Hibernate 条件调用,我想在一个 SQL 语句中执行。我正在尝试做的是选择具有一系列值(SQL IN 子句)中的属性的子级的父级实例,同时使用外连接加载子级。这是我目前所拥有的:

 Criteria c = session.createCriteria(Parent.class);

 c.createAlias("children", "c", CriteriaSpecification.LEFT_JOIN)
          .setFetchMode("c", FetchMode.JOIN)
          .add(Restrictions.in("c.property", properties));

 c.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);

 return c.list();

以下是一些示例数据:

Parent
Parent ID
A
B
C

Children
Child ID    Parent ID   property
...         A           0
...         A           2
...         A           7
...         B           1
...         C           1
...         C           2
...         C           3

如果其中一个孩子的属性等于我的绑定参数,我想要做的是返回父母和他们的所有孩子。假设 properties 是一个包含 {2} 的数组。在这种情况下,调用将返回父 A 和 C,但它们的子集合将仅包含元素 2。即家长[孩子]:

A[2] & C[2]

我想要的是:

A[0, 2, 7] & C[1, 2 3]

如果这不是一个错误,它似乎是一个损坏的语义。我看不出调用 A.getChildren() 或 C.getChildren() 并返回 1 条记录会被认为是正确的——这不是预测。 IE。如果我增加查询以使用默认选择提取,它会返回正确的子集合,尽管有大量查询:

  c.createAlias("children", "c").add(
      Restrictions.in("c.property", properties));

这是一个错误吗?如果没有,我怎样才能达到我想要的结果?

【问题讨论】:

    标签: java hibernate orm hibernate-criteria


    【解决方案1】:

    这可以通过变通方法来完成。

    Criteria c1 = session.createCriteria(Child.class);
    c1.add(Restrictions.in("property", properties));
    c1.setProjection( Projections.distinct( Projections.property( "parentId" ) ) );
    List<Integer> parentIds = c1.list();
    
    Criteria c2 = session.createCriteria(Parent.class);
    c2.createAlias("children", "children");
    c2.add(Restrictions.in("id", parentIds));
    return c2.list();
    

    【讨论】:

      【解决方案2】:
              Criteria c = session.createCriteria(Parent.class);
      
          c.createAlias("children", "children");
          c.add(Restrictions.in("children.property", properties));
      
           c.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);
      
           return c.list();
      

      【讨论】:

        【解决方案3】:

        我会从子类开始标准。您将获得一个包含所有子项的列表,然后您可以迭代并获取每个子项的父项。

        【讨论】:

          【解决方案4】:

          getChildren() 只是 getter/setter 的名称,您的查询将确定对象的填充方式。

          我猜这里第一部分吐出来了

          SELECT * FROM Parent 
          INNER JOIN Child c ON ... 
          WHERE c.property in (x,y,z) 
          

          这不会让你得到你想要的。如果您使用原始 SQL 编写此代码,您会想要做什么:

          SELECT * FROM Parent  
          WHERE ParentID IN (SELECT DISTINCT parentID FROM Child WHERE  c.property in (x,y,z))
          

          如果最后一个没有产生此查询,则适当地重新排列您的条件可能会奏效。 (您能否也发布一下hibernate为每个生成的内容?)

          【讨论】:

          • 对,SQL 是最简单的部分。我正在寻找的是标准调用。 ;) 另外,请记住,这将需要外部连接来填充子实体。
          • 那么第二个查询是获取父级并延迟加载子级吗?
          • 是的,对于返回的每个父记录,正在执行一个子查询,这是我试图避免的。看起来这实际上可能是一个缺陷,但我很好奇是否有人有解决方法:hibernate.onjira.com/browse/HHH-3524
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-02-16
          • 2011-05-07
          • 1970-01-01
          • 2011-06-23
          相关资源
          最近更新 更多