Hibernate CriteriaでManyToMany関係を照会する
-
06-07-2019 - |
質問
この問題を説明する方法がわからないので、私の質問をする最良の方法は例だと思います:
manyToMany関係を持つ2つのテーブルがあります:
DriversLicence <!> lt;-<!> gt; LicenceClass
LicenceClassは、<!> quot; Car <!> quot;、<!> quot; Motorbike <!> quot ;、および<!> quot; Medium Rigid <!> quot;のようなものです。
Hibernate Criteriaを使用して、<!> quot; Car <!> quot;の両方を持つすべてのライセンスを見つけるにはどうすればよいですか?および<!> quot; Motorbike <!> quot; LicenceClasses?
2008年12月11日更新 これは、カスタムResultTransformerを使用することで簡単に実現できることを発見しました。ただし、問題は、クエリが結果を返した後にのみ結果トランスフォーマが適用されることであり、実際にはSQLの一部にならないことです。私の質問は今<!> quot;であると思います。最初にSQLで説明したことを実行できますか?また、Hibernate Criteriaに類似したものはありますか?<!> quot;
解決
HQLを使用して最終的に達成した方法は次のとおりです。
public List<DriversLicence> findDriversLicencesWith(List<LicenceClass> licenceClasses) {
String hqlString = "select dl from DriversLicenceImpl dl where 1=1 ";
for (int i = 0; i < licenceClasses.size(); i++) {
hqlString += " and :licenceClass" + i + " = some elements(dl.licenceClasses)";
}
Query query = getSession().createQuery(hqlString);
for (int i = 0; i < licenceClasses.size(); i++) {
query.setParameter("licenceClass" + i, licenceClasses.get(i));
}
return query.list();
}
または、Hibernate CriteriaをsqlRestrictionとともに使用:
for (LicenceClass licenceClass : licenceClasses) {
criteria.add(Restrictions.sqlRestriction("? = some(select " + LicenceClass.PRIMARY_KEY + " from " +
LICENCE_CLASS_JOIN_TABLE + " where {alias}." +
DriversLicence.PRIMARY_KEY + " = " + DriversLicence.PRIMARY_KEY + ")",
licenceClass.getId(), Hibernate.LONG));
}
LICENCE_CLASS_JOIN_TABLEは、driversLicenceとLicenceClassの間の多対多の関係をサポートするためにhibernateが生成するテーブルの名前です。
他のヒント
引き続き、ドット表記を使用してリレーション全体で作業できます。たとえば、DriversLicence.licenceClassプロパティとLicenceClass.typeプロパティがあると仮定すると、次のようになります。
session.createCriteria(DriversLicence.class)
.add(Expression.or(
Expression.eq("licenceClass.type", "Car"),
Expression.eq("licenceClass.type", "Motorbike")
)
).list();
ただし、動的クエリではないため、この場合は単純に基準を使用することは避けますが、代わりに次を使用します。
session.createQuery("from DriversLicence where licenceClass.type in (:types)")
.setParameterList("types", myListOfTypes)
.list();
同様の問題がありましたが、HQLを使用して修正しました。クラス<!> quot; Enterprise <!> quot;これは、クラス<!> quot; User <!> quot;に関連しています。また、クラス<!> quot; Role <!> quot;に関連して、特定のユーザーに関連するすべての企業が必要な場合、多対多の関係が生じます。
Select e from Enterprise As e inner join e.Users As u inner join u.Roles As r
Where u.UserCode=?
あなたの場合、次のようなことをする必要があると思います;
Select dl from LicenceClass As l inner join l.DriversLicences As dl
Where
l.LicenseClass.Name = ? OR
l.LicenseClass.Name=? OR
l.LicenseClass.Name=?
お役に立てば幸いです。
別のオプションは、結合を連鎖することです(LicenseClassごとに1つの結合)。このような基準ビルダーと述語を使用しました
List<Predicate> predicates = new ArrayList<>();
for(Integer lcId : licenceClassIdList) {
SetJoin<DriversLicence, LicenceClass> dlClasses = dlRoot.join(DriversLicence_.licenceClasses);
predicates.add(builder.equal(dlClasses.get(LicenseClass_.id), lcId));
}
Predicate predicate = builder.and(predicates.toArray(new Predicate[predicates.size()]));
注意dlRootはRootクラスのオブジェクトであり、CriteriaQueryクラスから取得できます。結果の述語は、あなたが探しているものです...
'これがうまくいくとは思わない。 両方 <!> quot;車<!> quot;を持つすべてのライセンスを検索したいおよび<!> quot; Motorbike <!> quot; '
ニックが提供するスニペットで、Expression.or(....)の代わりにUser Expression.and(....)