Невозможно построить запрос с критериями API, используя и с другим И или вместе - PullRequest
1 голос
/ 21 января 2020

Я хочу построить простой запрос, подобный этому:

SELECT * FROM configuration WHERE store_type = 'REGULAR' AND (country = 'SG' OR country = 'AU')

И я пытаюсь добиться этого с помощью построителя критериев. Я пытаюсь создать динамический c построитель запросов, например, так:

Вы можете догадаться по имени объекта, это объект, который я буду использовать для динамического создания запроса

    data class SearchCriteria (
            val property: String,
            val values: List<String>,
            val operation: String
    )

Итак, в моем контроллере rest из пользовательского интерфейса я получу список этих объектов, и на основе них я хочу сгенерировать запрос.

Я создал класс спецификации, в котором я буду строить CriteriaBuilder и Predicates, и это выглядит так :

override fun toPredicate(root: Root<Configuration>, query: CriteriaQuery<*>, builder: CriteriaBuilder): Predicate? {
    val predicates: MutableList<Predicate> = mutableListOf()

    for (criteria in list) {
        if (criteria.operation == "EQUALS") {
            predicates.add(builder.equal(root.get<String>(criteria.key), criteria.values[0]))
        }

        if (criteria.operation == "EQUALS_OR") {
how to build below line dynamically ?
            predicates.add(builder.or(builder.like(root.get<String>(criteria.key), criteria.values[0]), builder.or(builder.like(root.get<String>(criteria.key), criteria.values[1]))))
        }
    }

    return builder.and(*predicates.toTypedArray())
}

Таким образом, в основном правила являются «простыми», если критерием является EQUALS, я хочу иметь простой предикат EQUAL, это просто и будет работать автоматически.

Фактическое осложнение состоит в том, чтобы смешать его с операцией EQUALS_OR, где мне нужно добавить это:

AND (someProperty = "value" или some property = "another value")

Другими словами, каждый раз, когда я получаю оператор EQUALS_OR, когда получаю несколько значений, я хочу построить AND (property = "value" OR property = "something else"), если у меня есть только одно значение, тогда оно будет простым и равным

Как вы можете предположить, мой текущее решение "работает", но мне пришлось с трудом создавать код, кто-нибудь знает, как я могу сделать эту строку динамической c?

predicates.add(builder.or(builder.like(root.get<String>(criteria.key), criteria.values[0]), builder.or(builder.like(root.get<String>(criteria.key), criteria.values[1]))))

Я создал этот код на основе этого руководства: https://attacomsian.com/blog/spring-data-jpa-specifications, в основном это одно и то же

1 Ответ

0 голосов
/ 22 января 2020

В случае, если кому-то это понадобится, я исправил эту проблему, как показано в коде ниже В основном я должен был понять, как правильно строить критерии.

override fun toPredicate(root: Root<Configuration>, query: CriteriaQuery<*>, builder: CriteriaBuilder): Predicate? {
    val predicates: MutableList<Predicate> = mutableListOf()

    for (criteria in list) {
        if (criteria.operation == "EQUALS") {
            predicates.add(builder.equal(root.get<String>(criteria.key), criteria.values[0]))
        }

        if (criteria.operation == "EQUALS_OR") {
            val equalsOrPredicates: MutableList<Predicate> = mutableListOf()
            for (value in criteria.values) {
                equalsOrPredicates.add(builder.and(builder.like(root.get<String>(criteria.key), value)))
            }

            predicates.add(builder.or(*equalsOrPredicates.toTypedArray()))
        }
    }

    return builder.and(*predicates.toTypedArray())
}
...