• 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());//得到总页数
        }
  • 相关阅读:
    [NOTE]常用Linux命令总结[Thx for commandlinefu]
    [原]隧道Proxy原理详解(基于Node.js)
    [转]MySQL索引详解(1)
    [QA]服务端进程模型
    [转]MySQL索引详解(2)
    非动态规划实现LCS算法
    Java里线程安全的有界容器的实现
    maven历史版本下载
    JDK9下载
    maven排除依赖和添加本地依赖
  • 原文地址:https://www.cnblogs.com/asndxj/p/11808539.html
Copyright © 2020-2023  润新知