Hibernate Criteria - 如何过滤嵌套子项?

时间:2011-08-04 12:27:40

标签: hibernate hibernate-criteria

我担心我可能会严厉地说出我的previous question,所以为了清楚起见,我正在重新开始。

描绘每个表之间存在OneToMany关联的多个表; 农场 - >字段 - > RegionGroup - >区域 即可。我正在尝试构建一个筛选 Region.nutrient 的Criteria查询。我已经看到很多人过滤顶层属性的例子,有时候下一层也是如此,但我不确定如何在深层过滤四层时构建查询。目前我有这个,这不起作用;

    Criteria criteria = getSessionFactory().getCurrentSession().createCriteria(Farm.class)
        .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
        .setFetchMode("fields.regionGroups", FetchMode.JOIN)
        .setFetchMode("fields.regionGroups.regions", FetchMode.JOIN)
        .createCriteria("fields.regionGroups.regions").add(Restrictions.in("nutrient", nutrients));

生成的主要SQL查询正确地覆盖了所需的结果(并且正是应该检索的数据集),但是,当您迭代返回的对象时, RegionGroup的关联 - >使用不包含限制的每次迭代的子查询执行区域,因此我得到 RegionGroup 的所有区域,而不管其值是多少 Region.nutrient ;

select
    ...
from
    Farm this_ 
inner join
    Business business3_ on this_.BusinessID=business3_.BusinessID 
left outer join
    Field fields4_ on this_.FarmID=fields4_.FarmID 
left outer join
    RegionGroup regiongrou5_ on fields4_.FieldID=regiongrou5_.FieldID 
inner join
    Region region1_ on regiongrou5_.RegionGroupID=region1_.RegionGroupID 
where
    region1_.nutrient in ( ? ) 

-------------------------------------------

select
    ...
from
    Region regions0_ 
where
    regions0_.RegionGroupID=?

我需要添加什么才能强制执行针对关联路径“fields.regionGroups.regions”指定的限制?

编辑:以下HQL实现了我所追求的目标,但不具备我所追求的定义灵活性,因此我想将其转换为Criteria查询;

from Farm as farm
  inner join fetch farm.fields as field
  inner join fetch field.regionGroups as regionGroup
  inner join fetch regionGroup.regions as region
where farm.id in :farmId 
  and field.id in :fieldId
  and region.nutrient in :nutrients

这给了我一个可以迭代的输出List<Farm>;

Farm [shortName=XYZ, name=XYZ]
   Field [shortName=COMM, name=Common]
      RegionGroup [indexNo=1]
         Region [nutrient=P, nutrientLevel=18.869684]
      RegionGroup [indexNo=2]
         Region [nutrient=P, nutrientLevel=18.836086]
      RegionGroup [indexNo=3]
         Region [nutrient=P, nutrientLevel=18.954369]

那么,如何将其指定为Criteria查询?为了证明它正在做我想做的事情,如果我只是改变HQL并删除Region.nutrient的限制,我会回到每个RegionGroup的所有区域;

from Farm as farm
  inner join fetch farm.fields as field
  inner join fetch field.regionGroups as regionGroup
  inner join fetch regionGroup.regions as region
where farm.id in :farmId 
  and field.id in :fieldId

对迭代结果的代码没有任何改变,我现在得到了这个;

Farm [shortName=XYZ, name=XYZ]
   Field [shortName=COMM, name=Common]
      RegionGroup [indexNo=1]
         Region [nutrient=Mg, nutrientLevel=108.84927]
         Region [nutrient=P, nutrientLevel=18.869684]
         Region [nutrient=pH, nutrientLevel=6.727207]
         Region [nutrient=K, nutrientLevel=189.04442]
      RegionGroup [indexNo=2]
         Region [nutrient=Mg, nutrientLevel=108.6944]
         Region [nutrient=pH, nutrientLevel=6.7214856]
         Region [nutrient=K, nutrientLevel=188.38605]
         Region [nutrient=P, nutrientLevel=18.836086]
      RegionGroup [indexNo=3]
         Region [nutrient=K, nutrientLevel=190.72464]
         Region [nutrient=pH, nutrientLevel=6.736169]
         Region [nutrient=P, nutrientLevel=18.954369]
         Region [nutrient=Mg, nutrientLevel=109.54382]

2 个答案:

答案 0 :(得分:0)

让我直截了当 - 您是否希望在返回的Farm列表中,他们只会填充部分 RegionRegionGroup

换句话说,我说Farm有2个Field个,每个RegionGroup个,每个Region个,每个Region's has the个,其中只有1个Farm个{ {1}}营养素`你正在寻找。

运行查询时,您将获得Field实例(正如您所希望的那样 - 它满足条件)。现在,您是否希望该实例只有1 RegionGroup,其中1 Region和1 Farm包含您的营养素?

那不会 - 不能发生。 Hibernate 保证对象的内存中表示与其持久状态匹配(当然是后置同步),并且执行上述操作与该原则相矛盾。如果这是可能的,那么在您决定修改并保存Field之后会发生什么? Hibernate现在应该从数据库中删除所有其他{{1}} s / etc ...吗?

如果这不是您要求的,请澄清您的问题。

答案 1 :(得分:0)

我有类似的目标,从第3级获取对象列表,条件匹配2个参数:主要父实体的第一个id和最内层实体的第二个id。 This is the question(抱歉,我只能将其添加到答案部分,因为我希望能够更快地关注并解决原始问题,因为我的个人资料声誉较低,我无法将其发布为评论)。感谢。