来自:https://www.jianshu.com/p/3c79125cc5cc
首先,dao接口需要继承JpaRepository与paSpecificationExecutor。
JpaSpecificationExecutor 方法列表
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);
findOne(spec):根据条件查询获取一条数据;
findAll(spec) :根据条件查询获取全部数据;
findAll(specification, pageable) : 根据条件分页查询数据,pageable:分页参数;pageable设定页码、一页数据量,同时返回的是Page类对象,可以通过getContent()方法拿到List集合数据;
findAll(specification, sort) : Sort:排序参数;根据条件查询并返回排序后的数据;
count(spec) : 获取满足当前条件查询的数据总数;
Specification :查询条件
自定义我们自己的Specification实现类
实现
//封装查询条件 Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb);
root:查询的根对象(查询的任何属性都可以从根对象中获取)
CriteriaQuery:顶层查询对象,自定义查询方式(了解:一般不用)
CriteriaBuilder:查询的构造器,封装了很多的查询条件
例如:
查询单个对象
案例:根据客户名称查询,查询客户名为传智播客的客户
查询条件
1.查询方式:cb对象
2.比较的属性名称:root对象
@Test public void testSpec() { /** * 自定义查询条件 * 1.实现Specification接口(提供泛型:查询的对象类型) * 2.实现toPredicate方法(构造查询条件) * 3.需要借助方法参数中的两个参数( * root:获取需要查询的对象属性 * CriteriaBuilder:构造查询条件的,内部封装了很多的查询条件(模糊匹配,精准匹配) * ) * */ //匿名内部类 Specification<Customer> spec = new Specification<Customer>() { @Override public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) { //1.获取比较的属性(custName为Customer实例类中的属性) Path<Object> custName = root.get("custName"); //2.构造查询条件 : select * from cst_customer where cust_name = '传智播客' /** * 第一个参数:需要比较的属性(path对象) * 第二个参数:当前需要比较的取值 */ //进行精准的匹配 (比较的属性,比较的属性的取值) Predicate predicate = cb.equal(custName, "传智播客"); return predicate; } }; Customer customer = customerDao.findOne(spec); System.out.println(customer); }
多条件查询
案例:根据客户名(传智播客)和客户所属行业查询(it教育)
@Test public void testSpec1() { /** * root:获取属性 * 客户名 * 所属行业 * cb:构造查询 * 1.构造客户名的精准匹配查询 * 2.构造所属行业的精准匹配查询 * 3.将以上两个查询联系起来 */ Specification<Customer> spec = new Specification<Customer>() { @Override 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, "传智播客");//第一个参数,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对象(属性),然后进行比较即可
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<?> query, CriteriaBuilder cb) { //查询属性:客户名 Path<Object> custName = root.get("custName"); //查询方式:模糊匹配 Predicate like = cb.like(custName.as(String.class), "传智播客%"); return like; } }; List<Customer> list = customerDao.findOne(spec); for (Customer customer : list) { System.out.println(customer); } }
查询全部(加入排序)
@Test public void testSpec3() { Specification<Customer> spec = new Specification<Customer>() { @Override 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.Direction.DESC:倒序 // Sort.Direction.ASC : 升序 //第二个参数:排序的属性名称 Sort sort = new Sort(Sort.Direction.DESC,"custId"); List<Customer> list = customerDao.findAll(spec, sort); for (Customer customer : list) { System.out.println(customer); } }
查询全部(加入排序)
/** * 分页查询 * Specification: 查询条件 * Pageable:分页参数 * 分页参数:查询的页码,每页查询的条数 * findAll(Specification,Pageable):带有条件的分页 * findAll(Pageable):没有条件的分页 * 返回:Page(springDataJpa为我们封装好的pageBean对象,数据列表,共条数) */ @Test public void testSpec4() { Specification spec = null; //PageRequest对象是Pageable接口的实现类 /** * 创建PageRequest的过程中,需要调用他的构造方法传入两个参数 * 第一个参数:当前查询的页数(从0开始) * 第二个参数:每页查询的数量 */ 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());//得到总页数 }