2012-03-29 110 views
6

任何人都可以幫助我獲得下面提到的JPA查詢的JPA標準查詢。如何使用JPA Criteria查詢編寫此查詢?

SELECT p,l FROM Person p 
LEFT JOIN Language l ON (p.language = l.language and l.locale like :locale) 
AND p.name like :name 
AND p.time BETWEEN :startDate 
AND :endDate order by name asc 
+0

你可以顯示你的人員和語言的實現嗎? – 2012-03-29 14:20:43

回答

10

假設人有關係的語言這裏就是你會在較老的Hibernate做什麼:

Criteria criteria = entityManager.createCriteria(Person.class); 
Criteria languageCriteria = criteria.createCriteria("language"); 

languageCriteria.add(Restrictions.like("locale", locale)); 

criteria.add(Restrictions.like("name", name)); 
criteria.add(Restrictions.between("time", startDate, endDate)); 

criteria.addOrder(Order.asc("name")); 

和我第一次嘗試在JPA 2.0:

CriteriaBuilder builder = entityManager.getCriteriaBuilder(); 
CriteriaQuery<Person> criteria = builder.createCriteria(Person.class); 
Root<Person> pRoot = criteria.from(Person.class); 
Join<Person, Language> langJoin = criteria.join("language", JoinType.LEFT); 

Predicate conjunction = builder.conjunction(); 

criteria.where(builder.and(
    builder.like(langJoin.get(Language_.locale), locale), 
    builder.like(pRoot.get(Person_.name), name), 
    builder.between(pRoot.get(Person_.time), startDate, endDate)); 

criteria.orderBy(builder.asc(pRoot.get(Person_.name))); 

請讓我知道如果這對你有用。

編輯:更新後的查詢僅使用一個where調用。

+4

限制不是JPA規範的一部分,它是休眠功能 – perissf 2012-03-29 14:58:56

+0

您是對的,我需要翻譯爲JPA 2 – 2012-03-29 15:10:13

+0

嘿,首先感謝,我應該把它放在這個問題上。 有沒有**關係** b/w實體的人和語言。人員和語言都有一個共同的列(語言(varchar)),我將加入該列。對我造成的問題是,我需要做一個** LEFT OUTER JOIN **,這樣如果沒有可用於該人的語言數據,我仍然應該能夠將語言對象的人員數據作爲空值。 – user1300877 2012-03-29 18:21:08

6

儘管johncarl給出的答案已被接受,但它對我來說並不正確。對於CriteriaQuery.where()的Javadoc說:

修改查詢根據 指定布爾表達式來限制查詢結果。替換之前添加的 限制(若有)。

據我瞭解,以下各行(給予限制)將覆蓋前面給出的限制:

criteria.where(builder.like(langJoin.get(Language_.locale), locale)); 
criteria.where(builder.like(pRoot.get(Person_.name), name)); 
criteria.where(builder.between(pRoot.get(Person_.time), startDate, endDate)); 

這意味着,在年底開始和結束日期之間只有最後一個限制( )將保持。

我threfore提出以下修改johncarl的回答是:

CriteriaBuilder builder = entityManager.getCriteriaBuilder(); 
CriteriaQuery<Person> criteria = builder.createCriteria(Person.class); 
Root<Person> pRoot = criteria.from(Person.class); 
Join<Person, Language> langJoin = criteria.join("language", JoinType.LEFT); 

Predicate[] restrictions = new Predicate[] { 
    builder.like(langJoin.get(Language_.locale), locale), 
    builder.like(pRoot.get(Person_.name), name), 
    builder.between(pRoot.get(Person_.time), startDate, endDate) 
}; 

criteria.where(builder.and(restrictions)); 

criteria.orderBy(builder.asc(pRoot.get(Person_.name))); 

但是,此代碼看起來真難看!請隨時編輯,如果它是錯誤的,並評論它,如果你看到更好的解決方案!我會很優雅!

+0

非常感謝您的提示。其中(...)不能逐漸使用,因爲它完全替代了可能通過的標準。另一方面,builder.and和(「where謂詞的數組」)工作的單個問題。很棒的解決方案,pho312 :) – Hartmut 2015-09-18 19:05:31

+0

謝謝你的提示!我完全喜歡你的方法。我只是簡單地補充說一個人可以創建一個ArrayList,並在他們出現時簡單地添加標準。另一方面,我不知道爲什麼,但pRoot.get(Person_.name)不適用於我。 Anume我用Person_語法得到一個錯誤。 – moldovean 2016-11-11 13:30:58