2014-10-30 109 views
-1

我想找到最簡單的解決方案,以查找具有查詢方法的情況,該查詢方法採用某個實體的某個屬性,並基於該屬性執行返回該實體的查詢。將參數添加到條件查詢的最簡單方法

問題是,如果我想添加更多可以搜索實體的屬性,使用jpa標準時最簡單的解決方案是什麼?這裏的一個方面是該方法必須是可移植的 - 如果稍後添加屬性,我不想重寫所有的代碼。

我知道這可以通過方法重載來完成,但我正在尋找更簡單的解決方案。

例如我的方法的代碼是:

public List<Car> findCar(String name) { 
     CriteriaBuilder cb = em.getCriteriaBuilder(); 
     CriteriaQuery<Car> c = cb.createQuery(Car.class); 
     Root<Car> d = c.from(Car.class); 
     Predicate condition = cb.equal(d.get(Car_.name), name); 
     c.where(condition); 
     TypedQuery<Car> q = em.createQuery(c); 
     List<Car> results = q.getResultList(); 

     return results; 
    } 

,如果我想在某種程度上,我可以搜索其他屬性租車實體擴展該查詢,例如,日期,應該怎麼辦。我不希望這種方法需要多個參數。

回答

0

我有點驚訝,這個問題以前沒有在這裏討論過。

所以我做了一些調查,想出了可能的答案。

最簡單的方法是擁有一個單獨的類f.x. CarSearchFilter中,你可以(通過其要執行的查詢,即參數)不同的過濾器:

public class CarSearchFilter { 

    private String name; 
    private Date date; 
    private String color; 
    //etc 

//getters and setters 

} 

當您要添加新的參數進行查詢,你只需要添加新的領域CarSearhFilter並修改查詢這樣方法。如果您不修改查詢方法,它仍然按原樣工作。這種API看起來很好。因此,findCar方法必須以這種方式修改:

public List<Car> findCar(CarSearchFilter filter) { 
    CriteriaBuilder cb = em.getCriteriaBuilder(); 
    CriteriaQuery<Car> c = cb.createQuery(Car.class); 
    Root<Car> d = c.from(Car.class); 

    // you have to add more predicates when you want more parameters 
    List<Predicate> predicates = new ArrayList<Predicate>(); 
    if (filter.getName() != null) { 
     predicates.add(cb.like(d.get(Car_.name), filter.getName())); 
    } 
    if (filter.getDate() != null) { 
     predicates.add(cb.lessThanOrEqualTo(d.get(Car_.date), filter.getDate())); 
    } 

    c.select(d).where(predicates.toArray(new Predicate[] {})); 
    TypedQuery<Car> q = em.createQuery(c); 
    List<Car> results = q.getResultList(); 

    return results; 
} 

還有其他方法可以執行此任務。作爲Tiny建議,可以使用鍵/值對的機制來存儲使用鍵作爲屬性/字段名和值字段的值搜索過濾器,但這種方法也有一些缺點:

  • 地圖是硬編碼
  • 你要存儲密鑰的地方
  • 打錯可以做到
相關問題