2011-06-02 41 views
1

我正在編寫一個將搜索文檔的JPA QL命名查詢。這應該只在一個查詢中完成,我不能切換到本機SQL(這是非功能性需求)。 查詢我寫如下所示:在@NamedQuery(JPA QL 1.0)中設置爲null的參數

query = "select doc from Doc doc " + 
" join doc.Csts cst " + 
" where cst.cstFrstNm like :FrstNm " + 
" and cst.cstLastNm like :LastNm " + 
" and doc.resId = :id "; 

此查詢參數化使用以下說明:

query.setParameter("FrstNm ", firstName + '%'); 
query.setParameter("LastNm ", lastName + '%');    
query.setParameter("id", resId); 

firstName, lastName, resId在上面的代碼是我的搜索條件,它們都是字符串,它們可以爲空。當它們中的一個爲空時,在查詢被調用時不應該考慮它。

例如:

假設:名字=「約翰」,姓氏=「李四」和渣油爲空,則查詢將返回所有的文件表對於用戶John Doe的條目,無問題是什麼是他們的resId。

我試圖把額外的OR和AND條件放到查詢中,檢查resId是否爲空,但它沒有工作。我正在HSQLDB上測試它。

有沒有辦法修改這個JPA查詢來處理空值?

回答

3

兩個解決方案:

首先一個,不要使用一個命名查詢,並創建了一個新的查詢爲每個請求:

boolean first = true; 
query = query = "select doc from Doc doc " + 
" join doc.Csts cst " + 
if (firstName != null) { 
    query += (first ? " where " : " and "); 
    query += " cst.cstFrstNm like :FrstNm "; 
    first = false; 
} 
query += ";"; 
// ... 

二的解決方案,您使用通配符。如果你的參數是空的,只是把一個「%」在您的查詢,這將匹配所有相應的字符串:

query.setParameter("FrstNm ", (firstName != null ? firstName : "") + '%'); 
query.setParameter("LastNm ", (lastName != null ? lastName : "") + '%'); 

如果的firstName是空的,你的查詢將是這樣的:

... cst.cstFrstNm like '%' ... 

和意志匹配所有的值。這將導致參數不會過濾任何結果,其行爲類似於不存在的行爲。

+0

非常感謝!其實我已經想過這些解決方法,但我希望有一些額外的方法。但似乎沒有JPA2.0這一切都可以完成。 – Lukasz 2011-06-02 15:26:05

+0

對於doc.resId =:resId |是否有可能我們'%'也爲=或在? – Synoon 2015-03-04 07:40:47

1

您可能需要動態構建查詢以滿足您的參數。例如:

public List<Employee> findEmployees(String name, String deptName, String projectName, String city) { 
    StringBuffer query = new StringBuffer(); 
    query.append("SELECT DISTINCT e "); 
    query.append("FROM Employee e LEFT JOIN e.projects p "); 
    query.append("WHERE "); 
    List<String> criteria = new ArrayList<String>(); 
    if (name != null) { criteria.add("e.name = :name"); } 
    if (deptName != null) { criteria.add("e.dept.name = :dept"); } 
    if (projectName != null) { criteria.add("p.name = :project"); } 
    if (city != null) { criteria.add("e.address.city = :city"); } 
    if (criteria.size() == 0) { 
    throw new RuntimeException("no criteria"); 
    } 
    for (int i = 0; i < criteria.size(); i++) { 
    if (i > 0) { query.append(" AND "); } 
     query.append(criteria.get(i)); 
    } 
    Query q = em.createQuery(query.toString()); 
    if (name != null) { q.setParameter("name", name); } 
    if (deptName != null) { q.setParameter("dept", deptName); } 
    if (projectName != null) { q.setParameter("project", projectName); } 
    if (city != null) { q.setParameter("city", city); } 
    return (List<Employee>)q.getResultList(); 
} 

如果您使用JPA 2.0進行此類任務,您也可以考慮使用Criteria API。

+0

@edolorzo:謝謝,我被告知要使用@NamedQuery,所以這種解決方法無濟於事,我不能使用JPA 2.0。 – Lukasz 2011-06-03 09:01:59