以前の質問の言い回しが悪かったのではないかと心配しているので、明確にするために新たに始めています。
各テーブル間に OneToMany 関連付けが存在する多数のテーブルを想像してください。Farm -> Field -> RegionGroup -> Region . Region.nutritionでフィルタリングする Criteria クエリを作成しようとしています。最上位レベルの属性でフィルタリングし、場合によっては次のレベルを下回っている人々の例をたくさん見てきましたが、4 層の深さでフィルタリングするときにクエリを作成する方法がわかりません。現時点ではこれがありますが、機能しません。
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の関連付けが制限を含まない各反復のサブクエリなので、 RegionGroup の値に関係なく、 RegionGroup のすべてのRegionsを取得します。
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」に対して指定された制限を適用するには、何を追加する必要がありますか?
EDIT:次のHQLは私が求めていることを行いますが、私が求めている定義の柔軟性がないため、基準クエリに変換したいと思います。
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.nutrition の制限を削除すると、RegionGroup ごとにすべての Region が返されます。
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]