10

この問題を説明する方法がわからないので、例を挙げて質問するのが最善の方法だと思います。

manyToMany 関係を持つ 2 つのテーブルがあります。

DriversLicence <-> LicenceClass

LicenceClass は、「Car」、「Motorbike」、「Medium Rigid」などです。

Hibernate Criteria を使用して、「Car」と「Motorbike」の両方の LicenceClasses を持つすべてのライセンスを見つけるにはどうすればよいですか?

2008 年 12 月 11 日更新 カスタム ResultTransformer を使用すると、これを簡単に実現できることがわかりました。ただし、問題は、クエリが結果を返した後にのみ結果トランスフォーマーが適用されることであり、実際には SQL の一部にはなりません。したがって、私の質問は「SQL で最初に説明したことを実行できますか? Hibernate Criteria のアナログはありますか?」ということになると思います。

4

5 に答える 5

6

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();
}

または、sqlRestriction で Hibernate Criteria を使用します。

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 が生成するテーブルの名前です。

于 2008-11-23T22:22:29.593 に答える
0

もう 1 つのオプションは、結合を連鎖させることです (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 クラスから取得できることに注意してください。結果の述語はあなたが探しているものです...

于 2016-10-04T12:13:13.323 に答える
0

同様の問題がありましたが、HQL を使用して修正しました。クラス「ユーザー」に関連し、クラス「ロール」にも関連するクラス「エンタープライズ」があります。関連するすべての企業が必要な場合、それらは多対多の関係にあります。特定のユーザーに対して、次のことを行います。

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=?

それが役に立てば幸い。

于 2008-11-12T03:12:13.843 に答える
0

リレーション全体で作業するためにドット表記を引き続き使用できます。たとえば、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();
于 2008-11-05T05:44:07.143 に答える
-1

「これはうまくいかないと思います。「自動車」と「オートバイ」の両方を持つすべてのライセンスを検索したい'

Nick が提供するスニペットの Expression.or(....) の代わりにユーザー Expression.and(....)

于 2008-11-07T08:48:58.173 に答える