Критерии гибернации - как отфильтровать вложенного ребенка? - PullRequest
3 голосов
/ 04 августа 2011

Боюсь, что я, возможно, плохо сформулировал свой предыдущий вопрос , поэтому я начинаю заново для ясности.

Изобразите количество таблиц, для которых существует связь OneToMany между каждой таблицей; Ферма -> Поле -> RegionGroup -> Регион . Я пытаюсь построить запрос Criteria, который будет фильтровать по Region.nutrient . Я видел множество примеров того, как люди фильтровали атрибуты верхнего уровня, а иногда и следующего уровня вниз, но я не уверен, как построить запрос при глубокой фильтрации четырех слоев. На данный момент у меня есть это, которое не работает;

    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. -> Region выполняется с подзапросом на каждой итерации, который не включает ограничение, поэтому я получаю все Regions из 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]

Итак, как мне указать это как запрос критерия? Чтобы доказать, что он делает то, что я хочу, если я просто изменю 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 голосов
/ 15 марта 2015

У меня аналогичная цель - получить список объектов с 3-го уровня с критериями, соответствующими 2 параметрам: 1-й идентификатор основной родительской сущности и 2-й идентификатор самой внутренней сущности. Это вопрос (извините, я мог добавить его только в раздел ответов, так как хотел получить более быстрое внимание и решение моего первоначального вопроса, и я не могу опубликовать его как комментарий из-за более низкой репутации на моемпрофиль).Спасибо.

0 голосов
/ 04 августа 2011

Позвольте мне получить это прямо - ожидаете ли вы, что в возвращенном списке Farm s они будут иметь только некоторые Region s и RegionGroup s заполненные?

Другими словами, скажем, у меня есть Farm с 2 Field с, каждый с 2 ​​RegionGroup с, каждый с 2 ​​Region с и только 1 из тех Region's has the питательных веществ, которые вы ищете для.

Когда вы выполните свой запрос, вы получите этот экземпляр Farm обратно (как следует - он удовлетворяет критериям). Теперь, вы ожидаете, что у этого экземпляра будет только 1 Field с 1 RegionGroup и 1 Region, содержащим ваше питательное вещество?

Этого не будет - НЕ МОЖЕТ произойти. Hibernate гарантирует , что представление вашего объекта в памяти соответствует его постоянному состоянию (конечно, после очистки), и выполнение чего-то подобного выше противоречит этому принципу. Если бы это было возможно, что бы произошло после того, как вы решили изменить и сохранить Farm? Должен ли Hibernate удалить все остальные Field s / etc ... из базы данных?

Если это не то, что вы спрашиваете, уточните свой вопрос.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...