JpaSpecificationExecutor 方法列表
T findOne(Specification spec):查询单个对象
List findAll(Specification spec):查询列表
Page findAll(Specification spec, Pageable pageable):分页查询
List findAll(Specification spec, Sort sort):查询列表
long count(Specification spec):统计查询
Specification :
Specification是查询条件,由我们自己实现。
需要实现Predicate toPredicate(Root root, CriteriaQuery<?> query, CriteriaBuilder cb)方法
实体类
package pers.zhang.entity;
/**
* @author zhang
* @date 2019/12/15 - 22:10
*/
import javax.persistence.*;
/**
* 1.实体类和表的映射关系
* @Entity
* @Table
* 2.类中属性和表中字段的映射关系
* @Id
* @GeneratedValue
* @Colum
*/
@Entity //声明实体类
@Table(name="cst_customer") //建立实体类和表的映射关系
public class Customer {
@Id//声明当前私有属性为主键
@GeneratedValue(strategy= GenerationType.IDENTITY) //配置主键的生成策略
@Column(name="cust_id") //指定和表中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;
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;
}
@Override
public String toString() {
return "Customer{" +
"custId=" + custId +
", custName='" + custName + '\'' +
", custSource='" + custSource + '\'' +
", custIndustry='" + custIndustry + '\'' +
", custLevel='" + custLevel + '\'' +
", custAddress='" + custAddress + '\'' +
", custPhone='" + custPhone + '\'' +
'}';
}
}
Dao接口
public interface MyCustomerDao extends JpaRepository<Customer, Long>, JpaSpecificationExecutor<Customer> {
}
测试类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class SpecTest {
@Autowired
private MyCustomerDao customerDao;
}
根据条件查询单个对象
方法名称 | 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 |
@Test
public void testSpec(){
/*
自定义查询条件:
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) {
//获取比较的属性
Path<Object> custName = root.get("custName");
//构造查询条件 select * from cst_customer where cust_name = '网易'
//第一个参数:需要比较的属性
//第二个参数:当前需要比较的取值
Predicate predicate = criteriaBuilder.equal(custName, "网易");//精准匹配
return predicate;
}
};
Customer customer = customerDao.findOne(spec);
System.out.println(customer);
}
多条件查询单个值
/*
多条件查询
示例:根据客户名(网页)和客户行业(游戏)查询客户
*/
@Test
public void testSpec1(){
/*
root:获取属性(客户名,所属行业)
criteriaBuilder:
1.构造客户名的精准匹配查询
2.构造所属行业的精准匹配查询
3.将以上两个查询联系起来
*/
Specification<Customer> spec = new Specification<Customer>() {
@Override
public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
Path<Object> custName = root.get("custName");
Path<Object> custIndustry = root.get("custIndustry");
//构造查询参数
//1.构造客户名的精准匹配
Predicate p1 = criteriaBuilder.equal(custName, "网易");
//2.构造所属行业的精准匹配
Predicate p2 = criteriaBuilder.equal(custIndustry, "游戏");
//3.将多个条件组合到一起,组合(满足条件一并且满足条件二:与关系 满足条件一或满足条件二即可:或关系)
Predicate and = criteriaBuilder.and(p1, p2);//以与的形式拼接多个查询条件
//criteriaBuilder.or() 以或的方式拼接条件
return and;
}
};
Customer customer = customerDao.findOne(spec);
System.out.println(customer);
}
查询列表
/*
查询列表:
示例:根据客户名称模糊匹配,返回客户列表
criteriaBuilder的方法:
equal:直接得到path对象(属性),然后进行比较
gt,lt,ge,le,like:得到path对象,根据句path指定比较的参数类型,再去进行比较
指定参数的类型:path.as(类型的字节码对象)
*/
@Test
public void testSpec3(){
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;
}
};
List<Customer> all = customerDao.findAll(spec);
for(Customer c : all)
System.out.println(c);
}
排序查询
/*
排序查询
示例:根据客户名称模糊匹配,逆序,返回客户列表
*/
@Test
public void testSpec4(){
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
需要调用构造方法传递参数
1. 排序的顺序(asc | desc)
2. 排序的属性名
*/
Sort sort = new Sort(Sort.Direction.ASC, "custName");
List<Customer> all = customerDao.findAll(spec);
for(Customer c : all)
System.out.println(c);
}
分页查询
Page接口
public interface Page<T> extends Iterable<T> {
int getNumber(); //当前第几页 返回当前页的数目。总是非负的
int getSize(); //返回当前页面的大小。
int getTotalPages(); //返回分页总数。
int getNumberOfElements(); //返回当前页上的元素数。
long getTotalElements(); //返回元素总数。
boolean hasPreviousPage(); //返回如果有上一页。
boolean isFirstPage(); //返回当前页是否为第一页。
boolean hasNextPage(); //返回如果有下一页。
boolean isLastPage(); //返回当前页是否为最后一页。
Iterator<T> iterator();
List<T> getContent(); //将所有数据返回为List
boolean hasContent(); //返回数据是否有内容。
Sort getSort(); //返回页的排序参数。
}
Pageable 接口:
/**
* 分页信息抽象接口
*
* @author Oliver Gierke
*/
public interface Pageable {
/**
* 返回要返回的页面.
*
* @return the page to be returned.
*/
int getPageNumber();
/**
* 返回要返回的项目的数量。
*
* @return the number of items of that page
*/
int getPageSize();
/**
* 根据底层页面和页面大小返回偏移量。
*
* @return the offset to be taken
*/
int getOffset();
/**
* 返回排序参数。
*
* @return
*/
Sort getSort();
}
/*
分页查询:
1.findAll(Specification, Pageable):有条件的分页
2.findALL(Pageable):没有条件的分页
Specification:查询条件
Pageable:分页参数
返回:Page(springdataJpa为我们封装好的pageBean对象)
*/
@Test
public void testSpec5(){
Specification spec = null;
/*
PageRequest是Pageable的实现类,在创建pageable的过程中,需要调用它的构造方法传入两个参数
1.当前查询的页数(从0开始)
2.每页查询的数量
*/
Pageable pageable = new PageRequest(0, 2);
Page page = customerDao.findAll(spec, pageable);
/*
Page方法:
getContent():获取查询的结果,返回List<?>
getTotalElements():获取查询到的总条数,返回Long
getTotalPages():获取查询到的总页数,返回int
*/
System.out.println("数据:" + page.getContent());
System.out.println("总条数:" + page.getTotalElements());
System.out.println("总页数" + page.getTotalPages());
}