Spring Data JPA的查詢方法

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中方法對應關係如下所示:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章