2016-03-02 57 views
0

也許這個問題有點不尋常,我只是不明白Criteria是如何工作的(很確定,因爲我剛開始學習它),但現在我有點困惑由以下問題:JPA 2 Criteria API通過加入集合中的某個元素進行比較

我實現了一個過濾功能,應該可以通過一定的標準填充一組記錄。因此,讓我們假設有下面的實體:

@Entity 
public class Car { 

    @OneToMany 
    private List<Deal> deals; 

} 

@Entity 
public class Deal { 

    private Customer customer; 

    private DateTime dealDate; 
} 

現在我得到第一客戶名稱來過濾車的記錄。所以理論上它看起來像:

private static List<Predicate> buildPredicates(Root root, CriteriaQuery query, 
CriteriaBuilder builder, CarFilter filter) { 
    List<Predicate> predicates = new ArrayList<>(); 
    ... 
predicates.add(
    builder.like(   
      root.get(Car_.deals.sortByDealDateComparator().first().customer.name), 
      filter.getFirstCustomerName())); 
    ... 
    return predicates; 
} 

我相信,這些交易應先加入,然後可能在某種程度上通過一個子查詢或東西來分類的。但是,如果僅使用CriteriaQuery來獲得第一個比較結果,那麼也很有趣。

我想我對此有誤,所以任何建議都會受到歡迎。

+0

非常令人困惑的問題。當你試圖通過名字獲得時,你爲什麼要關心排序交易?你得到的結果是什麼?你能指望什麼? –

+0

我同意這可能會引起混淆。因此,讓我們假設交易沒有按照任何標準排序。而且我基本上希望從最早的日期交易中獲得客戶的名字。 –

回答

0

那麼,你的一些問題是因爲你的實體hierarchy。您的層級根目錄中有Cars,但您需要使用Deals。如果您有Deals工作,得到自己想要的是(或多或少)直截了當:

CriteriaQuery<Deal> q = cb.createQuery(Deal.class); 
Root<Deal> root = q.from(Deal.class); 
CriteriaQuery<Deal> s = q.select(root).where(
     cb.like(root.get("customer").get("name").as(String.class), "Karl" ) 
    ).orderBy(cb.asc(root.get("dealDate"))); 
Deal deal = em.createQuery(s).getResultList().get(0); 

當然注意我沒有嘗試使用實體的元數據版本。在這裏,根被設置爲Deallikepredicate用於按名稱獲得Customers,並使用cb.asc對交易結果列表進行排序。第一個Deal取自結果列表,其中將包含Customer

如果你想回到Car你需要一個bidirectional關係映射,這你就加入到CarDeal與製圖ManyToOne做。

@ManyToOne 
private Car car; 

可能會或可能不會幫助,但是這應該給你一些思考。

+0

謝謝,尼古拉斯,但可能我應該提供關於這個問題的更多細節。這只是一個輔助方法,它構建謂詞以構建由Spring-Data-Jpa提供的規範。所以在這裏我不能訪問實體管理器。只需CriteriaQuery和CriteriaBuilder。 同樣在這個特定的例子中,我對Deal沒有真正的興趣,查詢應該會返回一個由此交易的屬性過濾的Cars列表... –

+0

發佈一個無法回答的問題沒有真正意義嗎? –

+0

種。我實際上找到了一個解決方法,爲每個交易添加序列號,這取決於年齡,所以最老的將始終有0序列。 然後得到我需要使用子查詢。 –