一.概述
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;
}
}