Как лучше всего обрабатывать параметры динамического запроса, используя Java & Spring - PullRequest
0 голосов
/ 02 ноября 2019

Проблема:

У меня есть конечная точка API, которая обрабатывает несколько параметров запроса. Он реализован с использованием Spring, а параметры запроса используются для запроса данных из базы данных postgres, которую я запрашиваю с помощью шаблона JDBC.

Я ищу технологию зрелого построителя запросов для решения моей проблемы.

Пример:

Тривиальный запрос может выглядеть примерно так:

api/book?name=LOTR&cover=hardback

Параметры запроса добавляются на карту, а строка запросапостроить из данных карт:

String sqlQuery += (String) map.entrySet().stream()
            .map(entry -> entry.getKey() + "='" + entry.getValue() + "' AND ")
            .collect(Collectors.joining());

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

Однако, еслизапрос, где искать что-то вроде

api/book?name=LOTR&name=Ulysses&cover=hardback

, теперь добавлено предложение "OR", которое приведенный выше код не обрабатывает. Я вижу себя быстро попадающим на территорию с утомительным разбором строк для создания операторов SQL.

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

Я хотел бы избежать использования любого ORM для этого проекта, поэтому о Hibernate и MyBatis не может быть и речи. Я рассмотрел некоторые примеры JOOQ, но они не выглядят совместимыми с шаблоном JDBC.

Ответы [ 2 ]

0 голосов
/ 05 ноября 2019

Наткнулся тут с таким же вопросом. Может быть, вы хотите взглянуть на RSQL 1

0 голосов
/ 03 ноября 2019

Для тривиальных реализаций, таких как ваш первый случай, когда вы должны удалить последнее И после того, как ваш запрос построен, существует простой хак - сразу после того, ГДЕ вы добавляете 1 = 1, а затем для каждого предиката ГДЕ вы добавляете И [КОЛОНКА] = [СТОИМОСТЬ].

Примечание: большинство баз данных оптимизируют использование констант в предложении WHERE перед выполнением, поэтому производительность не будет проблемой

/*
  select <columns> from <tables> where 1 = 1
  [dynamically built Where predicates will come here from following code] 
*/

String sqlQuery += (String) map.entrySet().stream()
    .map(entry -> "AND " + entry.getKey() + "='" + entry.getValue() + "'")
    .collect(Collectors.joining());

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

Вы можете найти хороший учебник здесь .

/* An example */
<select id = "getName_Id_phone" parameterType = "Student" resultType = "Student">
   SELECT * FROM STUDENT    
   <where>
      <if test = "id != null">
         id = #{id}
      </if>
      <if test = "name != null">
         AND name LIKE #{name}
      </if>
   </where>     
</select>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...