zoukankan      html  css  js  c++  java
  • springboot Jpa使用联合主键时需要动态生成条件并且要按照联合主键中某一个字段查询

    背景:前面有写过一篇使用springboot Jpa通过引入 JpaSpecificationExecutor 来实现动态生成查询条件的方式,主要代码如下。

     1   private Page<DrugApplyEntity> getDataList(DrugApplyInfoQuery query, Pageable pageable) {
     2         Specification<DrugApplyEntity> querySpecifi = new Specification<DrugApplyEntity>() {
     3             public Predicate toPredicate(Root<DrugApplyEntity> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
     4 
     5                 List<Predicate> predicates = new ArrayList<>();
     6                 if (!StringUtils.isEmpty(query.getBeginDate())) {
     7                     //大于或等于传入时间
     8                     predicates.add(criteriaBuilder.greaterThanOrEqualTo(root.get("applyTime").as(Date.class), query.getBeginDate()));
     9                 }
    10                 if (!StringUtils.isEmpty(query.getEndDate())) {
    11                     //小于或等于传入时间
    12                     predicates.add(criteriaBuilder.lessThanOrEqualTo(root.get("applyTime").as(Date.class), query.getEndDate()));
    13                 }
    14                 if (query != null) {
    15                     Class<? extends DrugApplyInfoQuery> clazz = query.getClass();
    16                     Field[] fields = clazz.getDeclaredFields();
    17                     for (Field tmpField : fields) {
    18                         tmpField.setAccessible(true);
    19                         try {
    20                             NotCondition annotation = (NotCondition) tmpField.getDeclaredAnnotation(NotCondition.class);
    21                             if (tmpField.get(query) != null && annotation == null) {
    22                                 String name = tmpField.getName();
    23                                 if(query.getIsFuzzySearch()){
    24 //                                    模糊匹配
    25                                     predicates.add(criteriaBuilder.like(root.get(name).as(String.class), "%"+ tmpField.get(query) + "%"));
    26                                 }else{  //精准查找
    27                                     predicates.add(criteriaBuilder.equal(root.get(name), tmpField.get(query)));
    28                                 }
    29                             }
    30                         } catch (Exception e) {
    31                             log.error("构建查询对象失败",e);
    32                         }
    33                     }
    34                 }
    35                 // and到一起的话所有条件就是且关系,or就是或关系
    36                 return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
    37             }
    38         };
    39         return drugApplyRepository.findAll(querySpecifi, pageable);
    40     }

    问题:现在有一个新的需要实现CURD的对象使用的是联合主键的方式 ,再直接使用之前的条件创建方法root.get(name) 就会报 org.springframework.data.mapping.PropertyReferenceException: No property name found for type  的错误 。但我仍然想继续通过一个查询实体类,根据实体类中的字段动态生成查询条件。查询了解到对于这种联合主键其中某一个字段作为查询条件的创建格式是如下方式

    root.get(<attribute embedded>).get(<subkey>)

    因此,将上面的getDataList方法修改一下,引入对于EmbedCondition自定义注解的判断,进而正确创建查询条件,主要代码如下:

    private Page<DeepSkuInfo> getDataList(DeepSkuInfoQuery query, Pageable pageable) {
            Specification<DeepSkuInfo> querySpecifi = new Specification<DeepSkuInfo>() {
                public Predicate toPredicate(Root<DeepSkuInfo> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
    
                    List<Predicate> predicates = new ArrayList<>();
                    if (!StringUtils.isEmpty(query.getBeginDate())) {
                        //大于或等于传入时间
                        predicates.add(criteriaBuilder.greaterThanOrEqualTo(root.get("lastModifyTime").as(Date.class), query.getBeginDate()));
                    }
                    if (!StringUtils.isEmpty(query.getEndDate())) {
                        //小于或等于传入时间
                        predicates.add(criteriaBuilder.lessThanOrEqualTo(root.get("lastModifyTime").as(Date.class), query.getEndDate()));
                    }
                    if (query != null) {
                        Class<? extends DeepSkuInfoQuery> clazz = query.getClass();
                        Field[] fields = clazz.getDeclaredFields();
                        for (Field tmpField : fields) {
                            tmpField.setAccessible(true);
                            try {
                                NotCondition annotation = (NotCondition) tmpField.getDeclaredAnnotation(NotCondition.class);
                                if (tmpField.get(query) != null && annotation == null) {
                                    String name = tmpField.getName();
                                    EmbedCondition embedCondition = (EmbedCondition) tmpField.getDeclaredAnnotation(EmbedCondition.class);
                                    if(query.getIsFuzzySearch()){
    //                                    模糊匹配
                                        if(embedCondition!=null){   //表示该查询字段是联合主键中的字段
                                            predicates.add(criteriaBuilder.like(root.get(embedCondition.superClassName()).get(name).as(String.class), "%"+ tmpField.get(query) + "%"));
                                        }else{
                                            predicates.add(criteriaBuilder.like(root.get(name).as(String.class), "%"+ tmpField.get(query) + "%"));
                                        }
                                    }else{  //精准查找
                                        if(embedCondition!=null) {   //表示该查询字段是联合主键中的字段
                                            predicates.add(criteriaBuilder.equal(root.get(embedCondition.superClassName()).get(name), tmpField.get(query)));
                                        }else{
                                            predicates.add(criteriaBuilder.equal(root.get(name), tmpField.get(query)));
                                        }
    
                                    }
                                }
                            } catch (Exception e) {
                                log.error("构建查询对象失败",e);
                            }
                        }
                    }
                    // and到一起的话所有条件就是且关系,or就是或关系
                    return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
                }
            };
            return  deepSkuInfoRepository.findAll(querySpecifi,pageable);
    
        }
    自定义注解代码如下:
    /**
     * 在jpa 条件查询反射时,针对使用联合主键的字段,由于需要使用 root.get(<attribute embedded>).get(<subkey>) 的形式,因此增加此注解,方便拼接查询条件使用
     */
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface EmbedCondition {
        String superClassName();
    }
  • 相关阅读:
    DLL编写教程
    Ogre 配置
    LNK1123: 转换到 COFF 期间失败: 文件无效或损坏
    C++编译,链接错误总结
    git基本操作
    实习第33天
    HTTP状态码整理
    Window下的WebStorm快捷键操作
    告别div,可以代替div的几个标签
    实习20天
  • 原文地址:https://www.cnblogs.com/falcon-fei/p/14983161.html
Copyright © 2011-2022 走看看