1.环境与上一篇一样( pom.xml applicationContext.xml )
2.创建 Dao层的接口 JpaSpecificationExecutor 就是用来实现 动态查询的接口 接规范
public interface CustomerDao extends JpaRepository<Customer,Long>, JpaSpecificationExecutor<Customer> {
}
根据条件,查询单个对象
T findOne( Specification<T> var1); Specification<T>就为自定义查询条件
1.实现Specification接口(提供泛型:查询的对象类型) 2.匿名内部类 实现toPredicate方法(构造查询条件)
3. 查询条件
1.查询方式CriteriaBuilder cb对象内置了许多查询方式 列如(like模糊查询,equal 等于查询)
2. 使用root对象 获取实体类中比较的属性名称
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class JpaSpecification {
@Autowired
private CustomerDao customerDao;
@Test
public void testSpec() {
Specification<Customer> spec = new Specification<Customer>() {
public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
//1.获取比较的属性
Path<Object> custName = root.get("custName");
//2.构造查询条件 : select * from cst_customer where cust_name = '传智播客'
Predicate predicate = cb.equal(custName, "wyc");//进行精准的匹配 (比较的属性,比较的属性的取值)
return predicate;
}
};
Customer customer = customerDao.findOne(spec);
System.out.println(customer);
}
多条件查询
1. root: 获取 实体类中的两个属性 客户名 ,所属行业
2. CriteriaBuilder cb:构造查询条件
1. 使用equal 构造客户名的精准匹配查询 2. 使用equal 构造所属行业的精准匹配查询
3.使用 CriteriaBuilder cb .and (p1,p2 ) 将以上两个查询联系起来(or | and) 4.返回Specification对象
@Test
public void testSpec1() {
Specification<Customer> spec = new Specification<Customer>() {
public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
Path<Object> custName = root.get("custName");//客户名
Path<Object> custIndustry = root.get("custIndustry");//所属行业
//构造查询
//1.构造客户名的精准匹配查询
Predicate p1 = cb.equal(custName, "wyc");//第一个参数,path(属性),第二个参数,属性的取值
//2..构造所属行业的精准匹配查询
Predicate p2 = cb.equal(custIndustry, "it教育");
//3.将多个查询条件组合到一起:组合(满足条件一并且满足条件二:与关系,满足条件一或满足条件二即可:或关系)
Predicate and = cb.and(p1, p2);//以与的形式拼接多个查询条件
// cb.or();//以或的形式拼接多个查询条件
return and;
}
};
Customer customer = customerDao.findOne(spec);
System.out.println(customer);
}
根据 客户名称的模糊匹配,返回客户列表
注意: 使用equal时直接的到path对象(属性),然后进行比较即可 List<T> findAll(Specification<T> var1);
使用 gt,lt,ge,le,like 时需要传入 实体类中属性的 类型的字节码对象 Path path.as( xxx.class )
@Test
public void testSpec5() {
//构造查询条件
Specification<Customer> spec = new Specification<Customer>() {
public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
//查询属性:客户名
Path<Object> custName = root.get("custName");
//查询方式:模糊匹配
Predicate like = cb.like(custName.as(String.class), "wyc%");
return like;
}
};
List<Customer> list = customerDao.findAll(spec);
for (Customer customer : list) {
System.out.println(customer);
}
}
使用模糊查询 并排序结果集
1. List<T> findAll(Specification<T> var1, Sort var2);
2.Sort(Sort.Direction direction, String... properties) 添加排序创建排序对象 ,需要调用构造方法实例化sort对象
第一个参数:排序的顺序(倒序,正序) Sort.Direction.DESC:倒序 Sort.Direction.ASC : 升序
第二个参数:需要根据 实体类中 那个属性进行排序
@Test
public void testSpec3() {
//构造查询条件
Specification<Customer> spec = new Specification<Customer>() {
public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
//查询属性:客户名
Path<Object> custName = root.get("custName");
//查询方式:模糊匹配
Predicate like = cb.like(custName.as(String.class), "传智播客%");
return like;
}
};
Sort sort = new Sort(Sort.Direction.DESC,"custId");
List<Customer> list = customerDao.findAll(spec, sort);
for (Customer customer : list) {
System.out.println(customer);
}
}
分页查询
1. Page<T> findAll( Specification<T> var1, Pageable var2 );
可以使用 findAll(Specification,Pageable):带有条件的分页 findAll(Pageable):没有条件的分页Specification=null即可
2.Pageable 接口的分页条件 使用它的实现类 PageRequest(int page, int size)
第一个参数:当前查询的页数(从0开始) 第二个参数:每页查询的数量
3.返回值 Page<T> Spring data jpa 为我们封装 好的pageBean对象 含有(数据列表,总条数, 总页数....)
@Test
public void testSpec4() {
Specification spec = null; 使用无条件的分页查询
//PageRequest对象是Pageable接口的实现类
Pageable pageable = new PageRequest(0,2);
//分页查询
Page<Customer> page = customerDao.findAll(null, pageable);
System.out.println(page.getContent()); //得到数据集合列表
System.out.println(page.getTotalElements());//得到总条数
System.out.println(page.getTotalPages());//得到总页数
}