Spring DataJPA的Specifications动态查询

JpaSpecificationExecutor接口的方法
T findOne(Specification<T> var1);  //查询单个对象

List<T> findAll(Specification<T> var1);  //查询列表
//查询全部 分页  Pageable:分页参数
//返回值:分页PageBean(springdatajpa提供的)
Page<T> findAll(Specification<T> var1, Pageable var2);
//查询列表,
//Sort:排序参数
List<T> findAll(Specification<T> var1, Sort var2);
//统计查询
long count(Specification<T> var1);
Specification对象:查询条件(进行查询时,需要自定义我们自己的Specification实现类)

实现的方法:

/*
* Root:代表查询的跟对象(查询的任何属性都可以从跟对象中获取)
* CriteriaQuery:顶层查询对象,自定义查询方式(了解)
* CriteriaBuilder:查询的构造器,封装了很多查询条件
*/
Predicate toPredicate(Root<T> var1, CriteriaQuery<?> var2, CriteriaBuilder var3);//封装查询条件
dao层接口
public interface CustomerDao extends JpaRepository<Customer,Integer>, JpaSpecificationExecutor<Customer> {

}
根据客户名查询客户
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class SpecTest {

    @Resource
    CustomerDao customerDao;

    /*
     * 根据条件,查询单个对象
     * */
    @Test
    public void testSpec(){
        //匿名内部类
        /*
        * 定义一查询条件,
        *   1.实现Specification接口(提供泛型,就是查询的对象类型)
        *   2.实现toPredicate方法(构造查询条件)
        *   3.需要借助方法参数中的两个参数(root:获取需要查询的对象属性;CriteriaBuilder:构造查询条件的,内部封装了很多查询条件(模糊匹配,精准匹配))
        *
        * 案例:根据客户名查询
        *   查询条件:
        *       1.查询方式,在CriteriaBuilder对象中
        *       2.比较的属性名称:在Root对象中
        * */
        Specification<Customer> spec = new Specification<Customer>() {
            public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) {
                //获取比较的属性
                Path<Object> name = root.get("name");
                //构造查询条件,select * from customer where name = "heima"
                //参数1:需要比较的属性Path对象 参数2;当前需要比较的取值
                Predicate predicate = cb.equal(name, "heima");//进行精准匹配,比较属性的取值
                return predicate;
            }
        };
        Customer customer = customerDao.findOne(spec);
        System.out.println(customer);
    }
}
多个条件进行查询(接口内容不需要写)
/*
* 多条件查询:根据客户名和客户所属行业进行查询
*  */
@Test
public void testSepc2(){
/*
* root:获取属性:客户名称,所属行业
* cb:构造查询
*   1.构造客户名的精准匹配查询
*   2.构造所属行业的精准匹配查询
*   3.将以上两个查询联系起来
* */
Specification<Customer> spec = new Specification<Customer>() {
public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) {
//获取客户名称,所属行业
Path<Object> name = root.get("name");
Path<Object> industry = root.get("industry");
//.构造客户名的精准匹配查询
Predicate predicate1 = cb.equal(name, "heima");
Predicate predicate2 = cb.equal(industry, "教育");
//将以上两个查询联系起来(组合:满足条件1并且满足条件2,满足条件1或者满足条件2)
Predicate predicate = cb.and(predicate1, predicate2);  //以与的形式拼接条件
//cb.or()  以或的方式拼接条件
return predicate;
}
};
Customer customer = customerDao.findOne(spec);
System.out.println(customer);
}
根据用户名进行模糊查询
/*
    * 案例:根据客户名进行迷糊查询
    * equal:直接得到path对象(属性),然后进行比较即可
    * gt lt le like:得到path对象,根据path指定比较的参数类型,再去进行比较 path.as(参数类型的字节码)
    * */
@Test
public void testSpec3(){
    Specification<Customer> spec = new Specification<Customer>() {
        public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) {
            Path<Object> name = root.get("name");
            Predicate predicate = cb.like(name.as(String.class), "%马%");
            return predicate;
        }
    };
    List<Customer> customerList = customerDao.findAll(spec);
    System.out.println(customerList);
}
根据客户名进行迷糊查询并按照id排序
/*
     * 案例:根据客户名进行模糊查询并按照id排序
     * */
@Test
public void testSpec4(){
    Specification<Customer> spec = new Specification<Customer>() {
        public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) {
            Path<Object> name = root.get("name");
            Predicate predicate = cb.like(name.as(String.class), "%马%");
            return predicate;
        }
    };
    //创建排序对象,需要调用构造方法实例化对象
    //参数1:排序的顺序(Sort.Direction.DESC:倒序 Sort.Direction.ASC:升序);参数2:排序的属性名
    Sort sort = new Sort(Sort.Direction.DESC,"id");
    List<Customer> customerList = customerDao.findAll(spec,sort);
    System.out.println(customerList);
}
分页查询
/*
* 分页查询
* findAll(Specification,Pageable):带有条件的分页
* findAll(Pageable):没有条件的分页
*   参数1:Specification
*   参数2:Pageable
*       查询的页码,每页查询的条数
*
* 返回:Page对象:SpringDataJpa为我们封装好的pageBean对象
* */
@Test
public void testSpec5(){
/*
* PageRequest树Pageable接口的实现类
* 创建PageRequest时需要调用构造方法传入两个参数
*   参数1:当前查询的页数(从0开始)
*   参数2:当前查询的总数
* */
Pageable pageable = new PageRequest(0,3);
//分页查询
Page<Customer> page = customerDao.findAll(pageable);
System.out.println(page.getTotalElements());  //表中的总条数
System.out.println(page.getTotalPages());   //得到总页数
System.out.println(page.getContent());   //得到结果列表,list集合
}