有時我們在查詢某個實體的時候,給定的條件是不固定的,這時就需要動態構建相應的查詢語句,在Spring Data JPA中可以通過JpaSpecificationExecutor接口查詢。相比JPQL,其優勢是類型安全,更加的面向對象。
import java.util.List; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.data.jpa.domain.Specification; /** * JpaSpecificationExecutor中定義的方法 **/ public interface JpaSpecificationExecutor<T> { //根據條件查詢一個對象 T findOne(Specification<T> spec); //根據條件查詢集合 List<T> findAll(Specification<T> spec); //根據條件分頁查詢 Page<T> findAll(Specification<T> spec, Pageable pageable); //排序查詢查詢 List<T> findAll(Specification<T> spec, Sort sort); //統計查詢 long count(Specification<T> spec); }
對於JpaSpecificationExecutor,這個接口基本是圍繞着Specification接口來定義的。我們可以簡單的理解為,Specification構造的就是查詢條件。
Specification接口中只定義了如下一個方法:
//構造查詢條件 /** * root :Root接口,代表查詢的根對象,可以通過root獲取實體中的屬性 * query :代表一個頂層查詢對象,用來自定義查詢 * cb :用來構建查詢,此對象里有很多條件方法 **/ public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb);
1 使用Specifications完成條件查詢
//依賴注入customerDao @Autowired private CustomerDao customerDao; @Test public void testSpecifications() { //使用匿名內部類的方式,創建一個Specification的實現類,並實現toPredicate方法 Specification <Customer> spec = new Specification<Customer>() { public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) { //cb:構建查詢,添加查詢方式 like:模糊匹配 //root:從實體Customer對象中按照custName屬性進行查詢 return cb.like(root.get("Name").as(String.class), "上海堡%"); } }; Customer customer = customerDao.findOne(spec); System.out.println(customer); }
2 基於Specifications的分頁查詢
@Test public void testPage() { //構造查詢條件 Specification<Customer> spec = new Specification<Customer>() { public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) { return cb.like(root.get("Name").as(String.class), "上海堡%"); } }; /** * 構造分頁參數 * Pageable : 接口 * PageRequest實現了Pageable接口,調用構造方法的形式構造 * 第一個參數:頁碼(從0開始) * 第二個參數:每頁查詢條數 */ Pageable pageable = new PageRequest(0, 5); /** * 分頁查詢,封裝為Spring Data Jpa 內部的page bean * 此重載的findAll方法為分頁方法需要兩個參數 * 第一個參數:查詢條件Specification * 第二個參數:分頁參數 */ Page<Customer> page = customerDao.findAll(spec,pageable); }
3 方法對應關系
方法名稱 |
Sql對應關系 |
equle |
filed = value |
gt(greaterThan ) |
filed > value |
lt(lessThan ) |
filed < value |
ge(greaterThanOrEqualTo ) |
filed >= value |
le( lessThanOrEqualTo) |
filed <= value |
notEqule |
filed != value |
like |
filed like value |
notLike |
filed not like value |