2016-05-13 50 views
4

我有一個查詢使用JOIN和ORDER BY,並希望使用Criteria Api在我的倉庫中使用它。JpaSpecificationExecutor JOIN + ORDER BY in Specification

在這裏,我發現,如何將這樣的查詢包裝到CriteriaQuery(Link)中。

CriteriaQuery<Pet> cq = cb.createQuery(Pet.class); 
Root<Pet> pet = cq.from(Pet.class); 
Join<Pet, Owner> owner = cq.join(Pet_.owners); 
cq.select(pet); 
cq.orderBy(cb.asc(owner.get(Owner_.lastName),owner.get(Owner_.firstName))); 

在另一邊,我發現了一些例子來使用標準API中結合有JpaRepository(example)。

的問題是,在庫中的所有方法需要一個規範:

T findOne(Specification<T> spec); 

它總是建立這樣的:

public static Specification<PerfTest> statusSetEqual(final Status... statuses) { 
    return new Specification<PerfTest>() { 
     @Override 

     public Predicate toPredicate(Root<PerfTest> root, CriteriaQuery<?> query, CriteriaBuilder cb) { 
      return cb.not(root.get("status").in((Object[]) statuses)); 
     } 
    }; 

} 

所以在一側,我知道如何創建一個CriteriaQuery中,另一方面,我需要一個由Predicate構建的規範,我無法弄清楚如何將CriteriaQuery解析爲規範/謂詞。

回答

6

嘗試是這樣的(我假設寵物有不少車主):

public static Specification<Pet> ownerNameEqual(String ownerName) { 
     return new Specification<Pet>() { 
      @Override 
      public Predicate toPredicate(Root<Pet> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) { 
       Join<Pet, Owner> owners = root.join("owners"); 
       criteriaQuery.orderBy(criteriaBuilder.desc(root.get("id"))); 
       return criteriaBuilder.equal(owners.get("name"), ownerName); 
      } 
     }; 
    } 

這僅僅是搜索,其至少一個業主所有寵物的例子有名稱等於OWNERNAME

但您可以在存儲庫中添加方法List<Pet> findByOwnersNameOrderByIdDesc(String ownerName);(作爲規範的等效項)。

+0

哇,我沒有預料到這個工作,因爲我沒想到後來使用了criteriaQuery,但它的工作原理 – aschi