zoukankan      html  css  js  c++  java
  • jpa之org.springframework.data.jpa.domain.Specification

     学习官方文档: https://docs.spring.io/spring-data/jpa/docs/2.3.3.RELEASE/reference/html

    Specification

    interface TaskRepository extends JpaRepository<Task, Integer>, JpaSpecificationExecutor<Task> 
    /**
    org.springframework.data.jpa.domain.Specification
        Predicate toPredicate(Root<T> var1, CriteriaQuery<?> var2, CriteriaBuilder var3);
            #Root : 实体类引用, 获取任何实体的属性
            #CriteriaQuery: 顶层查询条件,自定义查询 (where)(order by)  过滤掉关键字:from, where, order by等
            #CriteriaBuilder: 可构建底层查询条件,也可构建顶层查询条件 (like,equal,and,in,greaterThanOrEqualTo,lessThanOrEqualTo)  构建条件查询的语句
    
    criteria 规则
    criteria query 查询规则
    criteria builder 构建起规则
    restriction  限制
    **/

    Specification五个核心方法

        Optional<T> findOne(@Nullable Specification<T> var1);
    
        List<T> findAll(@Nullable Specification<T> var1);
    
        Page<T> findAll(@Nullable Specification<T> var1, Pageable var2);
    
        List<T> findAll(@Nullable Specification<T> var1, Sort var2);
    
        long count(@Nullable Specification<T> var1);

    无lambda表达式

    @Test
        public void test4(){
            Specification<Task> spec = new Specification<>() {
                @Override
                public Predicate toPredicate(Root<Task> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
                    Predicate p1 = builder.equal(root.get("status"), TaskStatusEnum.CREATED);
                    return query.where(p1).getRestriction();
                }
            };
            this.taskRepository.findAll(spec);
        }

    有lambda表达式

    @Test
        public void test4(){
            Specification<Task> spec = (root, query, builder) -> {
                Predicate p1 = builder.equal(root.get("status"), TaskStatusEnum.CREATED);
                return query.where(p1).getRestriction();
            };
            this.taskRepository.findAll(spec);
        }

    分页查询

    @Transactional
        @Test
        public void test5(){
            Specification<Task> spec = (root, query, builder) -> query.where().getRestriction();
            Page<Task> pageResult = this.taskRepository.findAll(spec, PageRequest.of(0, 10));
            pageResult.getContent().forEach(System.out::println);
            System.out.println("总页数:" + pageResult.getTotalPages());
            System.out.println("页面记录数:" + pageResult.getSize());
            System.out.println("当前页:" + pageResult.getNumber() + 1);
            System.out.println("总记录数:" + pageResult.getTotalElements());
        }

    简单order by

    @Test
        public void test6(){
            Specification<Task> spec = (root, query, builder) -> {
                root.fetch("owner");    //inner join user
                root.fetch("creator");  //inner join user
                root.fetch("model");    //inner join model
                root.fetch("client");   //inner join client
    
                Predicate p1 = builder.equal(root.get("name"), "上海福新");   //name=?
                Predicate p2 = builder.in(root.get("type")).value(TaskTypeEnum.BLACKOUT_APPLICATION).value(TaskTypeEnum.HIGH_USER_CHECK); //type in (?,?)
                Predicate p3 = builder.like(root.get("name"), "%" + "上海福新" + "%"); //name like %上海福新%
    
                return query.where(p1, p2, p3).getRestriction();
            };
            this.taskRepository.findAll(spec, Sort.by("name").descending()); //简单的order by
        }

    复杂order by

    @Test
        public void test7(){
            Specification<Task> spec = (root, query, builder) -> {
    
                root.fetch("owner");    //inner join user
                root.fetch("creator");  //inner join user
                root.fetch("model");    //inner join model
                root.fetch("client");   //inner join client
    
                //复杂自定义排序
                List<Order> orders = new ArrayList<>();
                orders.add(builder.asc(
                        builder.selectCase()
                                .when(builder.equal(root.get("status").as(TaskStatusEnum.class), TaskStatusEnum.CREATED), 1)
                                .when(builder.equal(root.get("status").as(TaskStatusEnum.class), TaskStatusEnum.FINISHED), 2)
                                .otherwise(3)
                ));
                query.orderBy(orders);
    
    
                Predicate p1 = builder.equal(root.get("name"), "上海福新");   //name=?
                Predicate p2 = builder.in(root.get("type")).value(TaskTypeEnum.BLACKOUT_APPLICATION).value(TaskTypeEnum.HIGH_USER_CHECK); //type in (?,?)
                Predicate p3 = builder.like(root.get("name"), "%" + "上海福新" + "%"); //name like %上海福新%
    
                return query.where(p1, p2, p3).getRestriction();
            };
            //this.taskRepository.findAll(spec, Sort.by("name").descending()); //简单的order by  query的排序和外面的排序同时存在时, 外面的会覆盖里面的排序
            this.taskRepository.findAll(spec);
        }

    CriteriaBuilder构建顶层查询条件写法

    @Test
        public void test8(){
            Specification<Task> spec = (root, query, builder) -> {
                Predicate p1 = builder.equal(root.get("name"), "上海福新");   //name=?
                Predicate p2 = builder.in(root.get("type")).value(TaskTypeEnum.BLACKOUT_APPLICATION).value(TaskTypeEnum.HIGH_USER_CHECK); //type in (?,?)
                Predicate p3 = builder.like(root.get("name"), "%" + "上海福新" + "%"); //name like %上海福新%
    
                //return query.where(p1, p2, p3).getRestriction();
                return builder.and(p1, p2, p3); //and
            };
            this.taskRepository.findAll(spec); 
        }

    左连接,内连接

     @Test
        public void test9(){
            Specification<Task> spec = (root, query, builder) -> {
                root.fetch("owner");    //inner join user  决定返回内容有owner
                root.fetch("creator");  //inner join user  决定返回内容有creator
                root.fetch("model");    //inner join model  决定返回内容有model
                root.fetch("client");   //inner join client  决定返回内容有client
    
                Predicate p1 = builder.equal(root.get("name"), "上海福新");   //name=?
                Predicate p2 = builder.in(root.get("type")).value(TaskTypeEnum.BLACKOUT_APPLICATION).value(TaskTypeEnum.HIGH_USER_CHECK); //type in (?,?)
                Predicate p3 = builder.equal(root.join("client", JoinType.LEFT).get("clientId"), 12); //左连接 left outer join  内连接 inner join  (会覆盖上面fetch的inner join)
    
                return builder.and(p1, p2, p3);
            };
            this.taskRepository.findAll(spec);
        }

    区别fetch和join:

    fetch决定返回结果有哪些字段,  此时如果没有join就默认inner join;

    join决定查询条件是left outer join还是inner join, 不考虑返回的内容;

    join: client

    select t1.* 
    from task t1
    inner join client t2 on t1.client_id=t2.client_id
    where 1=1

    fetch: client

    select t1.* , t2.*
    from task t1
    inner join client t2 on t1.client_id=t2.client_id
    where 1=1


  • 相关阅读:
    畜栏预定【贪心+小根堆】
    电影【离散化】
    最佳牛栏(前缀和+二分)
    防晒【贪心 + 平衡树】
    货仓选址【中位数】证明
    24个不易混淆的数字和字母,常用于密码或密钥
    win8上的新功能,不知道win7有木有,刚偶然发现的
    通过C#类库绘制正态分布的统计图(通用)
    C#组播消息收发
    使用c#类库绘制柱状图
  • 原文地址:https://www.cnblogs.com/smileblogs/p/13594478.html
Copyright © 2011-2022 走看看