1. 使用繼承的接口中的方法查詢
在繼承JpaRepository和JpaSpecificationExecutor接口後,我們就可以使用接口中定義的方法進行查詢。繼承JpaRepository後的方法列表:
繼承JpaSpecificationExecutor的方法列表:
2. 使用JPQL的方式查詢
使用Spring Data JPA提供的查詢方法已經可以解決大部分的應用場景,但是對於某些業務來說,我們還需要靈活的構造查詢條件,這時就可以使用@Query註解,結合JPQL的語句方式完成查詢。@Query註解的使用非常簡單,只需在方法上面標註該註解,同時提供一個JPQL查詢語句即可
public interface CustomerDao extends JpaRepository<Customer, Long>, JpaSpecificationExecutor<Customer> {
//使用jpql的方式查詢
@Query(value="from Customer")
public List<Customer> findAllCustomer();
//使用jpql的方式查詢,?1代表參數的佔位符,其中 1對應方法中的參數索引
@Query(value="from Customer where custName = ?1")
public Customer findCustomer(String custName);
}
此外,也可以通過使用@Query來執行一個更新操作,爲此,我們需要在使用@Query的同時,用@Modifying來將該操作標識爲修改查詢,這樣框架最終會生成一個更新的操作,而非查詢。
public interface CustomerDao extends JpaRepository<Customer, Long>, JpaSpecificationExecutor<Customer> {
@Query(value="update Customer set custName = ?1 where custId = ?2")
@Modifying
public void updateCustomer(String custName, Long custId);
}
3. 使用SQL的方式查詢
Spring Data JPA同樣也支持sql語句的查詢,如下:
public interface CustomerDao extends JpaRepository<Customer, Long>, JpaSpecificationExecutor<Customer> {
@Query(value="select * from cst_customer", nativeQuery=true)
public void findSql();
}
4. 方法命名規則查詢
顧名思義,方法命名規則查詢就是根據方法的名字,就能創建查詢。只需要按照Spring Data JPA提供的方法命名規則定義方法的名稱,就可以完成查詢工作。Spring Data JPA在程序執行的時候會根據方法名稱進行解析,並自動生成查詢語句進行查詢
按照Spring Data JPA定義的規則,查詢方法以findBy開頭,涉及條件查詢時,條件的屬性用條件關鍵字連接,要注意的是:條件屬性首字母需大寫。框架在進行方法名解析時,會先把方法名多餘的前綴截取掉,然後對剩下部分進行解析。
public interface CustomerDao extends JpaRepository<Customer, Long>, JpaSpecificationExecutor<Customer> {
//方法命名方式查詢(根據客戶名稱查詢客戶)
public Customer findByCustName(String custName);
}
具體的關鍵字,使用方法和生產成SQL如下表所示:
5. Specifications動態查詢
有時我們在查詢某個實體的時候,給定的條件是不固定的,這時就需要動態構建相應的查詢語句,在Spring Data JPA中可以通過JpaSpecificationExecutor接口查詢。相比JPQL,其優勢是類型安全,更加的面向對象。
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);
使用案例:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class SpecificationTest {
@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) {
Predicate p1 = cb.like(root.get("custName").as(String.class), "張%");
Predicate p2 = cb.equal(root.get("custIndustry").as(String.class), "IT");
//cb.and(以與的形式拼接多個查詢條件),cb.or(以或的形式拼接多個查詢條件)
Predicate and = cb.and(p1, p2);
return and;
}
};
Customer customer = customerDao.findOne(spec);
System.out.println(customer);
}
@Test
public void testSort() {
//構造查詢條件
Specification<Customer> spec = new Specification<Customer>() {
public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
return cb.like(root.get("custName").as(String.class), "張%");
}
};
//構造排序參數
Sort sort = new Sort(Sort.Direction.DESC, "custId");
List<Customer> list = customerDao.findAll(spec, sort);
for (Customer customer : list) {
System.out.println(customer);
}
}
@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("custName").as(String.class), "張%");
}
};
//構造分頁參數
Pageable pageable = new PageRequest(0, 5);
Page<Customer> page = customerDao.findAll(spec, pageable);
System.out.println(page.getContent()); //得到數據集合列表
System.out.println(page.getTotalElements()); //得到總條數
System.out.println(page.getTotalPages()); //得到總頁數
}
}
CriteriaBuilder中方法對應關係如下所示: