Как создать запрос с произвольным числом условий в предложении WHERE с использованием JPA - PullRequest
0 голосов
/ 15 сентября 2018

У меня есть объект, который состоит из полей String и Date. Как пользователь, заинтересованный в произвольном выборе, мне нужно построить запрос, который может содержать произвольное количество условий в предложении WHERE. Я хочу использовать JPA API. Полученный код выглядит следующим образом:

/**
 * 
 * @param start 1st result
 * @param size result set max size
 * @param filters WHERE search conditions. Key - entity field (column name), Value - search string or date range
 */
 public List<Entity> fetchEntities(int start, int size,
                                      Map<String, Object> filters) {
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<Entity> criteriaQuery = cb.createQuery(Entity.class);
        Root<Entity> root = criteriaQuery.from(Entity.class);
        applyFilters(filters, cb, criteriaQuery, root);
        CriteriaQuery<Entity> select = criteriaQuery.select(root);
        TypedQuery<Entity> query = em.createQuery(select);
        query.setFirstResult(start);
        query.setMaxResults(size);
        return query.getResultList();
    }

 private void applyFilters(Map<String, Object> filters, CriteriaBuilder cb, CriteriaQuery<?> criteriaQuery, Root<?> root) {
        if (filters != null && !filters.isEmpty()) {
            List<Predicate> predicates = new ArrayList<>();
            for (Map.Entry<String, Object> entry : filters.entrySet()) {
                String fieldName = entry.getKey();
                Object value = entry.getValue();
                if (value == null) {
                    continue;
                }
                Predicate p;
                if (Entity.isDateField(fieldName)) {
                    DateRange dateRange = (DateRange) value;
                    p = cb.between(root.get(fieldName), dateRange.getStart(), dateRange.getEnd());
                } else {
                    Expression<String> expr = root.get(fieldName).as(String.class);
                    p = cb.like(cb.lower(expr),
                            "%" + value.toString().toLowerCase() + "%");
                }
                predicates.add(p);
            }
            if (!predicates.isEmpty()) {
                criteriaQuery.where(cb.and(predicates.toArray(new Predicate[0])));
            }
        }
    }

Я заново изобретаю колесо? Есть ли более простые решения, чем приведенный выше код?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...