【问题标题】:Searching by several params at the same time Criteria Api多个参数同时搜索 Criteria Api
【发布时间】:2019-10-15 08:46:38
【问题描述】:

我有这个代码,它只适用于输入输入字符串的一个单词。但我想进行组合搜索。例如,我想写family和name,我想和同时拥有这个名字和family的人有结果。

 @Override
    public List<Teacher> searchByString(String str) {

        CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
        CriteriaQuery<Teacher> criteriaQuery = criteriaBuilder.createQuery(Teacher.class);
        Root<Teacher> TeacherRoot = criteriaQuery.from(Teacher.class);

        Predicate predicateForName
                = criteriaBuilder.like(criteriaBuilder.lower(TeacherRoot.get("name")), "%" + str.toLowerCase() + "%");

        Predicate predicateForFam
                = criteriaBuilder.like(criteriaBuilder.lower(TeacherRoot.get("fam")), "%" + str.toLowerCase() + "%");

        Predicate predicateForOtch
                = criteriaBuilder.like(criteriaBuilder.lower(TeacherRoot.get("otch")), "%" + str.toLowerCase() + "%");

        Predicate predicateForPhone
                = criteriaBuilder.like(TeacherRoot.get("phoneNumber"), "%" + str + "%");

        Predicate predicateForDate
                = criteriaBuilder.like(TeacherRoot.get("dateOfBirth").as(String.class), "%" + str + "%");

        Predicate predicateFinal = criteriaBuilder.or(
                predicateForName,
                predicateForFam,
                predicateForOtch,
                predicateForPhone,
                predicateForDate);

        criteriaQuery.where(predicateFinal);

        return em.createQuery(criteriaQuery).getResultList();

    }

样本数据:

1   John Newman      London      8-999990999
2   John Malkovich   Paris    8-999995999
3   John NewMan      Moscow      8-999995999

输入字符串:John Newman

结果记录:

1   John Newman   London   8-999990999
3   John NewMan   Moscow   8-999995999

输入字符串:John 5(姓名为 John 且电话号码为 5 的记录)

结果记录:

2   John Malkovich   Paris    8-999995999
3   John NewMan      Moscow   8-999995999

查询的组合可以不同。

【问题讨论】:

    标签: hibernate jpa search dao criteria-api


    【解决方案1】:

    使用指定的字符串字段(名称等)创建 searchCriteria 类,然后将其传递给 searchByString 方法。

    例如:

    public List<Teacher> searchByString(SearchCriteria criteria)
    

    内部方法只添加非空谓词:

    if(criteria.name != null) {
       //addPredicate
    }
    

    【讨论】:

      【解决方案2】:

      输入字符串 = John 5(姓名为 John 且电话号码为 5 的记录)

      使用您输入的谓词如下所示:

              Predicate predicateForName = criteriaBuilder.like(
                   criteriaBuilder.lower(TeacherRoot.get("name")), 
                   "%john 5%");
      
              //other predicates
      
              Predicate predicateForPhone = criteriaBuilder.like(
                    TeacherRoot.get("phoneNumber"),
                    "%John 5%");
      

      您尝试查找 name like "%john 5%"phoneNumber like "%John 5%" 的记录。

      您必须将输入字符串拆分为单词并为每个单词使用谓词。

      public List<Teacher> searchByString(String str) {
      
              CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
              CriteriaQuery<Teacher> criteriaQuery = criteriaBuilder.createQuery(Teacher.class);
              Root<Teacher> TeacherRoot = criteriaQuery.from(Teacher.class);
      
              Predicate predicateFinal = getPredicateByInput(str, criteriaBuilder);
      
              criteriaQuery.where(predicateFinal);
      
              return em.createQuery(criteriaQuery).getResultList();
      
      }
      

      public Predicate getPredicateByInput(String input, CriteriaBuilder criteriaBuilder) {
              String[] words = input.split(" ");
      
              Predicate predicate = null;
              for(String word : words) {
                Predicate wordPredicate = getPredicateByWord(word, criteriaBuilder);
      
                if(predicate == null) 
                    predicate = wordPredicate;
                else
                    predicate = criteriaBuilder.or(predicate, wordPredicate);
              }
      
              Objects.requireNonNull(predicate, "Null predicate is not allowed. Invalid input string '" + input + "'");
      
              return predicate;
      }
      

      private Predicate getPredicateByWord(String word, CriteriaBuilder criteriaBuilder) {
      
          Predicate predicateForName = criteriaBuilder.like(
                            criteriaBuilder.lower(TeacherRoot.get("name")), 
                            "%" + word.toLowerCase() + "%");
      
          Predicate predicateForFam = criteriaBuilder.like(
                            criteriaBuilder.lower(TeacherRoot.get("fam")), 
                            "%" + word.toLowerCase() + "%");
      
          Predicate predicateForOtch = criteriaBuilder.like(
                            criteriaBuilder.lower(TeacherRoot.get("otch")), 
                            "%" + word.toLowerCase() + "%");
      
          Predicate predicateForPhone = criteriaBuilder.like(
                           TeacherRoot.get("phoneNumber"), 
                           "%" + word + "%");
      
          Predicate predicateForDate = criteriaBuilder.like(
                           TeacherRoot.get("dateOfBirth").as(String.class), 
                           "%" + word + "%");
      
          return criteriaBuilder.or(
                              predicateForName,
                              predicateForFam,
                              predicateForOtch,
                              predicateForPhone,
                              predicateForDate);
      }
      

      like 子句是重量级的,所以你应该尽量避免多余的谓词

      【讨论】:

        猜你喜欢
        • 2012-11-18
        • 2015-12-29
        • 2015-10-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-11-13
        相关资源
        最近更新 更多