Подтвердить что ты не робот

(Как) я могу использовать "LIKE" в SQL-запросах с помощью MyBatis безопасно и DB-agnostic?

В MyBatis вы отмечаете места, где параметры должны быть вставлены в ваш SQL следующим образом:

SELECT * FROM Person WHERE id = # {id}

Этот синтаксис активирует правильное экранирование и т.д., чтобы избежать, среди прочего, атак SQL-инъекций. Если у вас есть доверенный ввод и вы хотите пропустить экранирование, вы можете вставить параметры дословно:

SELECT * FROM {tableName} WHERE id = # {id}

Теперь я хочу сделать LIKE-поиск на небезопасном входе, поэтому я хочу сделать следующее:

SELECT * FROM Person WHERE name LIKE # {beginOfName} || '%'

К сожалению, однако, важные серверы базы данных не поддерживают синтаксис || для конкатенации:

MSSQL - Прерывает стандарт, используя оператор "+" вместо "||".

...

MySQL - Плохо нарушает стандарт путем переопределения || означает OR.

Итак, я мог бы сделать

SELECT * FROM Person WHERE name LIKE CONCAT (# {beginOfName}, '%')

и ограничиваться, в данном случае, MySQL, или я мог бы сделать

SELECT * FROM Person WHERE name LIKE '{beginOfName}%'

и придется самостоятельно дезинформировать ввод.

Есть ли более элегантное решение?

4b9b3361

Ответ 1

Обычно это делается путем добавления % к самому параметру перед его передачей на любом языке, который вы используете вне SQL. Однако обратите внимание, что в любом случае вам может потребоваться выполнить шаг экранирования, если ваш поисковый запрос может содержать _ или %. См. Например этот вопрос для фона.)

Чтобы исправить проблему конкатенации в целом, поместите MySQL в ANSI sql_mode, и вы получите правильную поддержку для оператора ||, а также как правильная обработка двойных кавычек для имен схем, а не строковых литералов.

(Если вы не можете этого сделать, вам нужно будет построить функцию для построения выражения из || или CONCAT(), абстрагируя разницу.)

Ответ 2

Вы можете использовать синтаксис привязки

Цитата Официальная документация

Элемент bind позволяет создать переменную из выражения OGNL и привязать его к контексту. Например:

<select id="selectBlogsLike" resultType="Blog">
  <bind name="pattern" value="'%' + _parameter.getTitle() + '%'" />
  SELECT * FROM BLOG
  WHERE title LIKE #{pattern}
</select>

Ответ 3

привязка включает внутри if

<select id="select" parameterType="java.util.Map" resultType="ViajeDTO">

SELECT A.ID_VIAJE ID, A.NOMBRE, A.DESCRIPCION, A.FINICIO, A.FFIN, A.LOGO, A.URL, 
        A.ID_CLIENTE IDCLIENTE, B.NOMBRE CLIENTE
FROM VIAJE A
INNER JOIN CLIENTE B ON (A.ID_CLIENTE = B.ID_CLIENTE)
WHERE A.ESTATUS = 1 

<if test="P_NOMBRE != null">
    <bind name="pattern" value="'%' + P_NOMBRE + '%'" />
      AND A.NOMBRE LIKE #{pattern}
</if>
</select>

Ответ 4

Мы можем использовать Привязать. Элемент bind позволяет вам создать переменную из выражения и привязать ее к контексту. Например:

<select id="select" parameterType="java.util.Map" resultType="ViajeDTO">

    <bind name="pattern" value="'%' + P_NOMBRE + '%'" />

    SELECT A.ID_VIAJE ID, A.NOMBRE, A.DESCRIPCION, A.FINICIO, A.FFIN, A.LOGO, A.URL, 
            A.ID_CLIENTE IDCLIENTE, B.NOMBRE CLIENTE
    FROM VIAJE A
    INNER JOIN CLIENTE B ON (A.ID_CLIENTE = B.ID_CLIENTE)
    WHERE A.ESTATUS = 1 

    <if test="P_NOMBRE != null">
        AND A.NOMBRE LIKE #{pattern}
    </if>
</select>

Принимая во внимание, что параметр для поиска - P_NAME.

Ответ 5

Оператор

|| работал у меня в IBatis, но не в Mybatis.

В MyBatis мне пришлось использовать оператор +.

SELECT *
FROM Employee
WHERE
name like '%' + #{searchName,jdbcType=NVARCHAR} + '%'