Как динамически генерировать SQL-запрос на основе выбора пользователя? - PullRequest
2 голосов
/ 11 января 2010

Это тот же вопрос, что и:

Как динамически генерировать SQL-запрос на основе выбора пользователя?

Единственное отличие состоит в том, что мне интересно видеть решения, использующие также Java / JPA (+, возможно, EclipseLink или специальные расширения Hibernate).

Мне нужно создать графический интерфейс, с помощью которого пользователи могут выбирать несколько атрибутов, которые будут использоваться для запроса базы данных, чтобы найти подходящих людей. Я ищу идеи, как динамически генерировать запрос к базе данных в соответствии с выбором пользователя.

Запрос будет содержать несколько полей, но чтобы понять, в качестве примера я приведу только три из них:

  • Занятие - может быть от 0 до n строк занятости. Если указаны строки занятия, одна из них должна соответствовать.

  • Возраст - возраст можно указать как:

    1. точное совпадение (30)
    2. диапазон (например, 30-40)
    3. меньше значения (-40)
    4. больше значения (30 -)

Параметр возраста является необязательным в запросе. Кроме того, пользователь может указать, является ли возраст обязательным параметром. Если это не требуется, и в его профиле не указан возраст, критерии возраста для этого человека игнорируются.

  • Рост - аналогично возрасту

Примеры запросов:

Критерии не указаны:

select * from persons

Дано только занятие:

select * from persons where occupation = 'dentist'

Несколько профессий были даны:

select * from persons where (occupation = 'dentist' or occupation = 'engineer')

Возраст указан как значение, превышающее значение, и он должен существовать в профиле человека:

select * from persons where age >= 30

Рост указан как диапазон, и он не обязательно должен присутствовать в профиле человека:

select * from persons where (height is null or (height >= 30 and height <= 40))

Сочетание разных критериев:

select * from persons where occupation = 'dentist' and age >= 30 and (height is null or (height >= 30 and height <= 40))

Я уже реализовал код, который способен генерировать запросы в виде строк, но он, конечно, не слишком красив. Я ищу идеи, что было бы наиболее эффективным и красивым способом для достижения этой цели.

Ответы [ 5 ]

3 голосов
/ 27 сентября 2013

Существует много различных инструментов, которые, на мой взгляд, являются лучшими querydsl , torpedoquery e Object Query , эти три позволяют писать типобезопасный запрос, в противном случае вы можете использовать критерии api, и если вы используете jpa 2, также JPA2 Typesafe Query .

со всеми этими инструментами вы можете создать запрос во время выполнения !!

1 голос
/ 10 ноября 2011

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

1 голос
/ 04 февраля 2010

Если вы хотите сделать это в JPA 1.X, вы можете использовать пользовательский построитель запросов, как описано здесь http://rrusin.blogspot.com/2010/02/jpa-query-builder.html. Это позволяет создавать запросы следующим образом:

return new JpaQueryBuilder().buildQuery(em,
                new Object[] {
                    "select c from Car c where c.name is not null",
                    new JQBParam("name", name, " and c.name = :name"),
                    new JQBParam("type", type, " and c.type = :type")
                }
            )
1 голос
/ 11 января 2010

В Hibernate вы можете использовать Критерии запросов.

В Toplink мы получили Expression и ExpressionBuilder .

0 голосов
/ 11 января 2010

В моем коде для этого я использую объекты AND и OR. Они принимают списки в качестве параметров (выглядит хорошо с переменными аргументами Java 5) и объединяют их в строки с необходимыми пробелами и скобками. Псевдокод:

AND(WhereCond ... conds) { this.conds = conds; }
toString() { return conds.length == 0 ? "" : "(" + join(conds, " AND ") + ")" };

где join() преобразует массив объектов в массив строк, а затем соединяет элементы с параметром.

...