一.概述
JpaSpecificationExecuto是通過方法的參數類型進行查詢。
二.常用方法
T findOne(Specification spec); //查詢單個對象
List findAll(Specification spec); //查詢列表
//查詢全部,分頁
//pageable:分頁參數
//返回值:分頁pageBean(page:是springdatajpa提供的)
Page<T> findAll(Specification<T> spec, Pageable pageable);
//查詢列表
//Sort:排序參數
List<T> findAll(Specification<T> spec, Sort sort);
long count(Specification<T> spec);//統計查詢
三.常用對象【查詢條件】
-
Specification :查詢條件
自定義我們自己的Specification實現類 實現 //root:查詢的根對象(查詢的任何屬性都可以從根對象中獲取) //CriteriaQuery:頂層查詢對象,自定義查詢方式(瞭解:一般不用) //CriteriaBuilder:查詢的構造器,封裝了很多的查詢條件
Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb); //封裝查詢條件
四.範例
1.測試類
(1)代碼塊
import cn.dao.CustomerDao;
import cn.pojo.Customer;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.persistence.criteria.*;
import java.util.List;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class SpecTest {
@Autowired
private CustomerDao customerDao;
@Test
/**
* 查詢單個對象
*/
public void test1(){
//設置查詢的條件
/**
* 自定義查詢條件
* 1.實現了Specification接口,泛型是操作的實體類對象
* 2.實現了toPredicate方法(構造查詢條件)
* 3.需要藉助方法的倆個參數
* Root:獲取需要查詢的對象屬性
* CriteriaBuilder:構造查詢條件,內部封裝了很多的查詢條件(模糊查詢,精準查詢等)
*
* 案例:根據客戶名稱查詢,查詢客戶名爲李明的客戶
* 查詢條件:
* 1.查詢方法:CriteriaBuilder對象
* 2.比較的屬性名稱:Root對象
*/
Specification<Customer> spec = new Specification<Customer>() {
@Override
public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
//1.獲取比較的屬性
Path<Object> custName = root.get("custName");//參數是實體類的屬性名稱
//2.構造查詢方式:select * from cst_customer where cust_name = "小李"
//方法:equal是查詢條件
//參數一:是path對象,比較的屬性
//參數二:是比較的取值
Predicate predicate = criteriaBuilder.equal(custName, "小李");
return predicate;
}
};
//使用的JpaSpecificationExecuto類中的findOne
Customer customer = customerDao.findOne(spec);
//驗證結果
System.out.println(customer);
}
@Test
/**
* lambda表達式實現
*/
public void test2(){
Specification<Customer> spec = (Root<Customer> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder)->{
//1.獲取比較的屬性
Path<Object> custName = root.get("custName");//參數是實體類的屬性名稱
//2.構造查詢方式:select * from cst_customer where cust_name = "小李"
//方法:equal是查詢條件
//參數一:是path對象,比較的屬性
//參數二:是比較的取值
Predicate predicate = criteriaBuilder.equal(custName, "小李");
return predicate;
};
//使用的JpaSpecificationExecuto類中的findOne
Customer customer = customerDao.findOne(spec);
//驗證結果
System.out.println(customer);
}
@Test
/**
* 多條件查詢
*/
public void test3(){
Specification<Customer> spec = new Specification<Customer>() {
@Override
public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
//1.獲取比較的屬性
Path<Object> custName = root.get("custName");//參數是實體類的屬性名稱
Path<Object> custId = root.get("custId");//參數是實體類的屬性名稱
//2.構造查詢方式:精準查詢
// select * from cst_customer where cust_name = "小李" and cust_id = 1l
//2.1查詢條件一
Predicate predicate = criteriaBuilder.equal(custName, "小李");
//2.2查詢條件二
Predicate predicate2 = criteriaBuilder.equal(custId, 1l);
//2.3組合條件or,and
Predicate and = criteriaBuilder.and(predicate, predicate2);//以與的形式拼接條件
// criteriaBuilder.or();//以或的形式拼接條件
return and;
}
};
//使用的JpaSpecificationExecuto類中的findOne
Customer customer = customerDao.findOne(spec);
//驗證結果
System.out.println(customer);
}
@Test
/**
* 模糊查詢
*/
public void test4(){
Specification<Customer> spec = new Specification<Customer>() {
@Override
public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
//1.獲取比較的屬性
Path<Object> custName = root.get("custName");//參數是實體類的屬性名稱
//2.構造查詢方式:精準查詢
// select * from cst_customer where cust_name like "%李%"
//2.1查詢條件
//模糊參數的參數一爲字段的數據類型(需要通過Path對象【實體類對象】的as方法進行設置)
//模糊參數的參數二爲字段的取值
Predicate predicate = criteriaBuilder.like(custName.as(String.class),"%李%");
return predicate;
}
};
//使用的JpaSpecificationExecuto類中的findOne
List<Customer> list = customerDao.findAll(spec);
for(Customer customer : list) {
//驗證結果
System.out.println(customer);
}
}
@Test
/**
* 排序查詢
*/
public void test5(){
Specification<Customer> spec = new Specification<Customer>() {
@Override
public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
Path<Object> custName = root.get("custName");//參數是實體類的屬性名稱
Predicate predicate = criteriaBuilder.like(custName.as(String.class),"%李%");
return predicate;
}
};
//設置排序
//參數一,設置排序
//參數二:排序的屬性名
Sort sort = new Sort(Sort.Direction.DESC,"custId");//實體類的屬性名:custId
List<Customer> list = customerDao.findAll(spec,sort);
for(Customer customer : list) {
//驗證結果
System.out.println(customer);
}
}
@Test
/**
* 分頁查詢
* findAll方法
* 參數一:查詢條件
* 參數二:分頁信息,
* 屬性有分頁條數,分頁起始點的記錄
*/
public void test6(){
Specification<Customer> spec = new Specification<Customer>() {
@Override
public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
Path<Object> custName = root.get("custName");//參數是實體類的屬性名稱
Predicate predicate = criteriaBuilder.like(custName.as(String.class),"%李%");
return predicate;
}
};
//創建分頁對象
//參數一:當前查詢的頁數【起始點】
//參數二:每頁顯示的記錄數
Pageable pageable = new PageRequest(0,2);
Page<Customer> page = customerDao.findAll(spec, pageable); //有查詢條件使用的方法
// Page<Customer> page = customerDao.findAll(null, pageable); //沒有查詢條件使用的方法
System.out.println(page.getTotalElements());//獲取每頁顯示記錄的個數方法:getTotalElements()
System.out.println(page.getContent());//獲取查詢的結果集getContent()
System.out.println(page.getTotalPages());//獲取總頁數getTotalPages()
}
}
(2)返回值爲單個對象的查詢條件
(3)多條件查詢
(4)模糊查詢
(5)排序查詢
(6)分頁查詢
2.pojo實體類
(1)代碼塊
@Entity
@Table(name = "cst_customer")
public class Customer implements Serializable {
/**
* 主鍵聲明
*/
@Id
/*
GeneratedValue聲明主鍵的自增加模式
IDENTITY:是底層數據庫必須支持自動增長
SEQUENCE:是底層數據庫必須支持序列
TABLE:jpa提供的一種機制,通過一張數據庫表的形式完成主鍵增長
AUTO:自動選擇類型IDENTITY或SEQUENCE
*/
@GeneratedValue(strategy = GenerationType.TABLE)
@Column(name="cust_id")
private Long custId;
@Column(name="cust_name") //指定和表中cust_name字段的映射關係
private String custName;
@Column(name="cust_source")//指定和表中cust_source字段的映射關係
private String custSource;
@Column(name="cust_industry")//指定和表中cust_industry字段的映射關係
private String custIndustry;
@Column(name="cust_level")//指定和表中cust_level字段的映射關係
private String custLevel;
@Column(name="cust_address")//指定和表中cust_address字段的映射關係
private String custAddress;
@Column(name="cust_phone")//指定和表中cust_phone字段的映射關係
private String custPhone;
@Override
public String toString() {
return "Customer{" +
"custId=" + custId +
", custName='" + custName + '\'' +
", custSource='" + custSource + '\'' +
", custIndustry='" + custIndustry + '\'' +
", custLevel='" + custLevel + '\'' +
", custAddress='" + custAddress + '\'' +
", custPhone='" + custPhone + '\'' +
'}';
}
public Long getCustId() {
return custId;
}
public void setCustId(Long custId) {
this.custId = custId;
}
public String getCustName() {
return custName;
}
public void setCustName(String custName) {
this.custName = custName;
}
public String getCustSource() {
return custSource;
}
public void setCustSource(String custSource) {
this.custSource = custSource;
}
public String getCustIndustry() {
return custIndustry;
}
public void setCustIndustry(String custIndustry) {
this.custIndustry = custIndustry;
}
public String getCustLevel() {
return custLevel;
}
public void setCustLevel(String custLevel) {
this.custLevel = custLevel;
}
public String getCustAddress() {
return custAddress;
}
public void setCustAddress(String custAddress) {
this.custAddress = custAddress;
}
public String getCustPhone() {
return custPhone;
}
public void setCustPhone(String custPhone) {
this.custPhone = custPhone;
}
}