2008-11-05 91 views
9

我不知道如何來形容這個問題,所以我覺得一個例子是問我的問題的最佳途徑:與Hibernate查詢條件的關係多對多

我有兩個表具有多對多關係:

DriversLicence < - > LicenceClass

LicenceClass是像「汽車」,「摩托車」和「中等剛性」的東西。

使用Hibernate標準,我如何找到同時擁有「Car」和「Motorbike」LicenceClass的所有許可證?

更新12/11/2008 我發現使用自定義的ResultTransformer可以輕鬆實現。然而,問題是隻有在查詢返回結果後纔會應用結果轉換器,結果轉換器實際上不會成爲SQL的一部分。所以我想現在我的問題是「你可以做我最初在SQL中描述的東西 - 是否有Hibernate Criteria模擬?」

回答

5

以下是我最後用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的標準與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之間的一對多關係。

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(); 
+0

我不認爲這會工作。 我想查找** **「Car」和「Motorbike」LicenceClass **的所有許可證。都不是**。 – 2008-11-05 05:57:53

+0

啊......好點。雖然不是最有效的,你可以: 從DriversLicence DL選擇DL加入d.licenceType LT 其中 「汽車」=一些元素(lt.type) 和 「摩托車」=一些元素(lt.type) 這也可以更改爲使用標準(超出字符!) – Nick 2008-11-06 01:46:20

-1

'我不認爲這會起作用。我想查找所有擁有的許可證「Car」和「Motorbike」'

用戶Expression.and(....)而不是Expression.or(....)代替Nick提供的代碼片段

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

希望它有幫助。

0

另一個選項是鏈接連接(每個LicenseClass一個連接)。我使用的標準建造和謂詞這樣

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是根類的對象,你可以從CriteriaQuery中類得到它。導致的謂詞是你在找什麼...