Как: термин запроса Mybatis с одинарной кавычкой / апострофом

У меня есть страница поиска, которая использует введенный пользователем термин для запроса базы данных. Я использую Mybatis 3.4.0 с Spring.

Проблема в том, что Mybatis удаляет все одинарные кавычки в поисковом запросе, вне зависимости от того, экранирую я их или нет. Это допустимые запросы, поскольку пользователь должен иметь возможность искать такие строки, как O'Toole, но ничего не возвращается.

Вот фрагмент кода из картографа. Рассматриваемое поле - caseWhereConditionDTO.value, а входящее значение, например, O''TOOLE (вручную экранировано в коде)

<if test="caseWhereConditionDTO.value != null">
    ${caseWhereConditionDTO.leftExpression}
    ${caseWhereConditionDTO.operator} 
    #{caseWhereConditionDTO.value}
    ${caseWhereConditionDTO.closeConditionString}
</if>

что приводит к предложению where

where  UPPER(p.last_name ||', ' || p.first_name ) LIKE 'OTOOLE%'

в котором отсутствует двойной сбежавший O''TOOLE

Все работает нормально, когда в маппере я заменяю # на $ и заключаю в одинарные кавычки

'${caseWhereConditionDTO.value}' 

в результате получается вывод sql

where  UPPER(p.last_name ||', ' || p.first_name ) LIKE 'O''TOOLE%'

который дает ожидаемые результаты запроса

но, конечно, я хотел бы сохранить защиту от SQL-инъекций #{}

Итак, мой вопрос: как мне запросить термины с одинарными кавычками, все еще используя защиту SQL-инъекций оператора #{}/prepared?


person Evan G    schedule 26.04.2017    source источник
comment
Если вы уже вручную экранируете caseWhereConditionDTO.value с помощью двойных кавычек, не могли бы вы вместо этого использовать синтаксис текстового литерала? Например, просмотрите docs.oracle.com/cd /B19306_01/server.102/b14200/, и поработайте над созданием предложения where, например where q'[UPPER (p.last_name ||' , ', ' || p.first_name ), например 'O'TOOLE% ']'   -  person Michael Peacock    schedule 26.04.2017


Ответы (1)


Есть 2 варианта, где нет необходимости экранировать одинарные кавычки:

  • Если нет уверенности, что входные данные не будут содержать никаких %, они должны быть экранированы в первую очередь (если они существуют во входных данных и не экранированы, это создаст путаницу для SQL: является ли % частью входных данных или "оператором"?), затем соедините % со значением: value = value + "%";, а затем LIKE #{value}.

  • Лучший вариант — просто объединить % в запросе SQL: LIKE #{value} || '%'. Работает, только что перепроверил.

person blackwizard    schedule 27.04.2017
comment
Я не уверен, что понимаю, проблема не в % , а в ' ', который удаляется - person Evan G; 27.04.2017
comment
отредактированный ответ: кавычки не требуют экранирования, тогда как % может. - person blackwizard; 27.04.2017
comment
Теперь я вижу, да, я объединяю % отдельно, в моем фрагменте сопоставления, это «${caseWhereConditionDTO.closeConditionString}», который является %. не могли бы вы более подробно рассказать о кавычках, не нуждающихся в экранировании? mybatis удаляет кавычки независимо от того, избегаю я их или нет - person Evan G; 27.04.2017
comment
кавычки, не требующие экранирования : означает, что вы не применяете предварительную обработку вашего значения, передаете его как есть. Кроме того, забудьте 1-й вариант, который я предложил, используйте 2-й: не объединяйте в java/mybatis, делайте в SQL, что означает caseWhereConditionDTO.closeConditionString="|| '%'" - person blackwizard; 27.04.2017