zoukankan      html  css  js  c++  java
  • SpringData_03_Specifications动态查询

    有时我们在查询某个实体的时候,给定的条件是不固定的,这时就需要动态构建相应的查询语句,在Spring Data JPA中可以通过JpaSpecificationExecutor接口查询。相比JPQL,其优势是类型安全,更加的面向对象。  

    1.对于JpaSpecificationExecutor,这个接口基本是围绕着Specification接口来定义的。我们可以简单的理解为,Specification构造的就是查询条件。

    Specification接口中只定义了如下一个方法:

    //构造查询条件
        /**
        *    root    :Root接口,代表查询的根对象,可以通过root获取实体中的属性
        *    query    :代表一个顶层查询对象,用来自定义查询
        *    cb        :用来构建查询,此对象里有很多条件方法
        **/
        public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb);

     1.通过单个条件查询对象

    /**
         * 根据条件查询单个对象
         */
        @Test
        public void testFindOne() {
            //匿名内部类
            /**
             * 自定义查询条件
             *      1.实现Specification接口(提供泛型:查询的对象类型)
             *      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());//得到总页数
        }
  • 相关阅读:
    牛客练习赛51 D题
    Educational Codeforces Round 72 (Rated for Div. 2) C题
    Codeforces Round #583 (Div. 1 + Div. 2, based on Olympiad of Metropolises) C题
    Codeforces Round #583 (Div. 1 + Div. 2, based on Olympiad of Metropolises) A题
    Codeforces Round #583 (Div. 1 + Div. 2, based on Olympiad of Metropolises) A题
    Educational Codeforces Round 72 (Rated for Div. 2) B题
    Educational Codeforces Round 72 (Rated for Div. 2) A题
    《DSP using MATLAB》Problem 7.2
    《DSP using MATLAB》Problem 7.1
    《DSP using MATLAB》Problem 6.24
  • 原文地址:https://www.cnblogs.com/asndxj/p/11808539.html
Copyright © 2011-2022 走看看