使用JPA Conjuction编写条件语句 - Criteria API

时间:2018-03-26 09:03:15

标签: java jpa criteria-api

我需要将此查询复制到 JPA CriteriaBuilder 代码中:

....
WHERE (
        (lower(userdto0_.city) LIKE '%istanbul%')
        OR 
        (lower(userdto0_.city) LIKE '%ankara%')
      )
      AND 
        (lower(TO_CHAR(cast(user1_.id AS varchar(255)))) LIKE 1)

这是代码;

public Page<UserDTO> findByCriteria(String sort, Pageable pageable, Map<String, List<String>> filtersMap) {
....
        Root<UserDTO> iRoot = cq.from(UserDTO.class);
        Join<UserDTO, User> bJoin = iRoot.join("user");
        List<Predicate> predicates = new ArrayList<Predicate>();


        cq.multiselect(bJoin.get("id"), bJoin.get("login"), bJoin.get("firstName"), bJoin.get("lastName"),
                bJoin.get("dayOfBirth"), iRoot.get("district"), iRoot.get("city"));

        filtersMap.entrySet().stream().filter(v -> v.getValue() != null && v.getValue().size() > 0).forEach(entry -> {
            entry.getValue().forEach(k -> {

                try {
                    bJoin.<String>get(entry.getKey()).as(String.class);

                    Expression<String> e1 = bJoin.<String>get(entry.getKey()).as(String.class);
                    Expression convertedColumnName = cb.function("TO_CHAR", String.class, e1);
                    predicates.add(cb.like(cb.lower(convertedColumnName), "%" + k.toLowerCase() + "%"));
                } catch (Exception e) {
                    if (!k.isEmpty()) {
                        if (!iRoot.<String>get(entry.getKey()).getJavaType().toString().contains("String")) {
                            Expression<String> e1 = iRoot.<String>get(entry.getKey()).as(String.class);
                            Expression convertedColumnName = cb.function("TO_CHAR", String.class, e1);
                            predicates.add(cb.like(convertedColumnName, "%" + k + "%"));
                        } else {
                            predicates.add(
                                    cb.like(cb.lower(iRoot.<String>get(entry.getKey())), "%" + k.toLowerCase() + "%"));
                        }
                    }
                }
            });

        });

        columnName = new ArrayList<String>();
        filtersMap.entrySet().stream().distinct().filter(v -> v.getValue() != null && v.getValue().size() > 0 && !columnName.add(v.getKey())).forEach(entry -> {
            for (int i = 0 ; i < filtersMap.size() ; i++) {
                columnName.add(entry.getKey());
            }
        });


        Predicate[] predArray = new Predicate[predicates.size()];
        finalQuery = cb.disjunction();

        columnName.forEach(name -> {
            if (name.equals("city")) {
                finalQuery = cb.or(predicates.toArray(predArray));
                predicates.add(cb.or(predicates.toArray(predArray)));
                cq.where(finalQuery);
            } else {
                predicates.toArray(predArray);
                cq.where(predArray);
            }
        });

.....

}

但我的sql看起来像上面的代码;

....
WHERE (lower(userdto0_.city) LIKE '%istanbul%')
  OR (lower(userdto0_.city) LIKE '%ankara%')
  AND (lower(TO_CHAR(cast(user1_.id AS varchar(255)))) LIKE 1)

这会产生不同的结果。

我知道我应该使用结合() disjunction()方法,但我是JPA的新手,所以我不知道如何使用他们使格式正确。

1 个答案:

答案 0 :(得分:0)

我通过添加 cb.conjuction()

解决了这个问题

我的工作代码现在看起来像这样;

    public Page<UserDTO> findByCriteria(String sort, Pageable pageable, Map<String, List<String>> filtersMap) {
            ......
            List<Predicate> predicatesOr = new ArrayList<Predicate>();
            List<Predicate> predicatesAnd = new ArrayList<Predicate>();

            cq.multiselect(bJoin.get("id"), bJoin.get("login"), bJoin.get("firstName"), bJoin.get("lastName"),
                    bJoin.get("dayOfBirth"), iRoot.get("district"), iRoot.get("city"));

            filtersMap.entrySet().stream().filter(v -> v.getValue() != null && v.getValue().size() > 0).forEach(entry -> {
                entry.getValue().forEach(k -> {

                    try {
                        bJoin.<String>get(entry.getKey()).as(String.class);

                        Expression<String> e1 = bJoin.<String>get(entry.getKey()).as(String.class);
                        Expression convertedColumnName = cb.function("TO_CHAR", String.class, e1);
                        if (entry.getValue().size() > 1) {
                            predicatesOr.add(cb.like(cb.lower(convertedColumnName), "%" + k.toLowerCase() + "%"));
                        }else {
                            predicatesAnd.add(cb.like(cb.lower(convertedColumnName), "%" + k.toLowerCase() + "%"));
                        }
                    } catch (Exception e) {
                        if (!k.isEmpty()) {
                            if (!iRoot.<String>get(entry.getKey()).getJavaType().toString().contains("String")) {
                                Expression<String> e1 = iRoot.<String>get(entry.getKey()).as(String.class);
                                Expression convertedColumnName = cb.function("TO_CHAR", String.class, e1);
                                if (entry.getValue().size() > 1) {
                                    predicatesOr.add(cb.like(convertedColumnName, "%" + k + "%"));
                                }else {
                                    predicatesAnd.add(cb.like(convertedColumnName, "%" + k + "%"));
                                }
                            } else {
                                if (entry.getValue().size() > 1) {
                                    predicatesOr.add(cb.like(cb.lower(iRoot.<String>get(entry.getKey())), "%" + k.toLowerCase() + "%"));
                                }else {
                                    predicatesAnd.add(cb.like(cb.lower(iRoot.<String>get(entry.getKey())), "%" + k.toLowerCase() + "%"));
                                }
                            }
                        }
                    }
                });

            });

            Predicate[] predArrayOr = new Predicate[predicatesOr.size()];
            Predicate[] predArrayAnd = new Predicate[predicatesAnd.size()];

            predicatesOr.toArray(predArrayOr);
            predicatesAnd.toArray(predArrayAnd);

            finalQuery = cb.or(predArrayOr);
            andQuery = cb.and(predArrayAnd);
            Predicate pFinal = predArrayOr.length >= 2 ? cb.and(cb.or(finalQuery), andQuery) : cb.and(cb.or(cb.conjunction(), finalQuery), andQuery);

            cq.where(pFinal);
......
}

这一行;

Predicate pFinal = predArrayOr.length >= 2 ? cb.and(cb.or(finalQuery), andQuery) : cb.and(cb.or(cb.conjunction(), finalQuery), andQuery);

完美无缺。