SpringData_03_Specifications dynamic query

Sometimes we query an entity when a given condition is not fixed, then you need to dynamically build the appropriate query, you can query the interface by JpaSpecificationExecutor in the Spring Data JPA. Compared JPQL, its advantage is type safety, more object-oriented.  

1. For JpaSpecificationExecutor, this interface is basically around Specification interface definition. We can simply be understood as, Specification query is constructed.

Only Interface Specification defines a method as follows:

// constructor query 
    / **
    * Root: Root interface for the root object query can be acquired entity attributes root
    * Query: on behalf of a top-level query object, used to customize the query
    * Cb: to build a query, this object, there are many methods Conditions
    **/
    public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb);

 1. single condition query object

/**
     * Based on a single object query condition
     */
    @Test
    public  void testFindOne () {
         // anonymous inner classes 
        / **
         * Custom query
         * 1. Implement Interface Specification (providing generic: the object type queries)
         *      2.实现toPredicate方法(构造查询条件)
         *      3.需要借助方法参数中的两个参数(
         *          root:获取需要查询的对象属性
         *          CriteriaBuilder:构造查询条件的,内部封装了很多的查询条件(模糊匹配,精准匹配)
         *       )
         *  案例:根据客户名称查询,查询客户名为传智播客的客户
         *          查询条件
         *              1.查询方式
         *                  cb对象
         *              2.比较的属性名称 实体类名称
         *                  root对象
         *
         */
        Specification<Customer> spec = new Specification<Customer>() {

            @Override
            public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) {
                //1.获取比较的属性
                Path<Object> custName = root.get("custName");
                //2.构造查询条件  :    select * from cst_customer where cust_name = 'hdh'
                Predicate predicate = cb.equal(custName, "hdh");//进行精准的匹配  (比较的属性,比较的属性的取值)
                return predicate;
            }
        };
        Customer customer = customerSpecDao.findOne(spec);
        System.out.println(customer);
    }

2.通过多个字段条件查询对象

/**
     * 多条件查询
     *      案例:根据客户名(传智播客)和客户所属行业查询(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> p1 = root.get("custName");
                Path<Object> p2 = root.get("custIndustry");
                Predicate custName  = cb.equal(p1, "hdh");
                Predicate custIndustry  = cb.equal(p2, "it");

                Predicate equal = cb.and(custName, custIndustry);
                return equal;
            }
        };
        Customer customer = customerSpecDao.findOne(spec);
        System.out.println(customer);
    }

3.模糊排序查询

/**
     * 案例:完成根据客户名称的模糊匹配,返回客户列表
     *      客户名称以 ’h‘ 开头
     *
     * 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), "h%");
                return like;
            }
        };
//        List<Customer> list = customerDao.findAll(spec);
//        for (Customer customer : list) {
//            System.out.println(customer);
//        }
        //添加排序
        //创建排序对象,需要调用构造方法实例化sort对象
        //第一个参数:排序的顺序(倒序,正序)
        //   Sort.Direction.DESC:倒序
        //   Sort.Direction.ASC : 升序
        //第二个参数:排序的属性名称
        Sort sort = new Sort(Sort.Direction.DESC,"custId");
        List<Customer> list = customerSpecDao.findAll(spec, sort);
        for (Customer customer : list) {
            System.out.println(customer);
        }
    }

4.分页查询

/**
     * 分页查询
     *      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 = customerSpecDao.findAll(null, pageable);
        System.out.println(page.getContent()); //得到当前页数据集合
        System.out.println(page.getTotalElements());//得到总条数
        System.out.println(page.getTotalPages());//得到总页数
    }

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Guess you like

Origin www.cnblogs.com/asndxj/p/11808539.html