Как создать выражение CriteriaBuilder во время выполнения для вложенных атрибутов? - PullRequest
0 голосов
/ 03 июня 2019

Я пытаюсь создать универсальный метод для глубокой фильтрации, используя Criteria API.

Например, если я хочу отфильтровать атрибут "id.person.name" или более 3 вложенных атрибутов.

У меня уже работает фильтр для 2 вложенных атрибутов, например: "person.name".

Условие elseif ниже работает с 3-мя вложенными атрибутами, но я пытаюсь создать метод, который мне не нужно менять, если появляется новый случай.

private <T> List<Predicate> filterInDepth(Map<String, String> params, Root<T> root,
        CriteriaBuilder criteriaBuilder, String field, Class<T> clazz)
        throws NoSuchFieldException {
    List<Predicate> predicates = new ArrayList<>();
    String[] compositeFields = field.split(REGEX_FIELD_SPLITTER);
    if (compositeFields.length == 2) {
        Join<Object, Object> join = root.join(compositeFields[0]);
        predicates.add(criteriaBuilder.equal(join.get(compositeFields[1]),
                params.get(field)));
    }
    else if (clazz.getDeclaredField(compositeFields[0]).getType()
            .getDeclaredField(compositeFields[1]).getType()
            .getDeclaredField(compositeFields[2]) != null) {
        predicates.add(criteriaBuilder.equal(root.get(compositeFields[0])
                .get(compositeFields[1]).get(compositeFields[2]), params.get(field)));
    }
    return predicates;
}

Итак, я пытаюсь разбить строку, создать цикл и создать выражение. Но я не мог выразить выражения.

1 Ответ

0 голосов
/ 03 июня 2019

Я нашел решение, надеюсь, помогу кому-нибудь.

private <T> List<Predicate> filterInDepth(Map<String, String> params, Root<T> root,
        CriteriaBuilder criteriaBuilder, String field, Class<T> clazz)
        throws NoSuchFieldException {
    List<Predicate> predicates = new ArrayList<>();
    String[] compositeFields = field.split(REGEX_FIELD_SPLITTER);

    if (isNestedFieldExists(clazz, compositeFields)) {
        Path path = null;
        for (String part : compositeFields) {
            if (path == null) {
                path = root.get(part);
            }
            else {
                path = path.get(part);
            }
        }

        predicates.add(criteriaBuilder.equal(path, params.get(field)));
    }

    return predicates;
}

private boolean isNestedFieldExists(Class clazz, String[] fieldChain)
        throws NoSuchFieldException {
    for (String field : fieldChain) {
        Field f = clazz.getDeclaredField(field);
        if (f.getType() == null) {
            return false;
        }

        clazz = f.getType();
    }

    return true;
}
...