Java SQL Escape без использования setString - PullRequest
1 голос
/ 13 июля 2011

Есть ли встроенный метод для экранирования строки для SQL? Я бы использовал setString, но бывает, что я использую setString несколько раз в одном и том же комбинированном операторе SQL, и было бы лучше (я думаю), если бы выход происходил только один раз, а не каждый раз, когда я говорю setString. Если бы в переменной была экранированная строка, я мог бы использовать ее повторно.

Нет ли способа сделать это на Java?

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

String q = '%' + request.getParameter("search") + '%';
PreparedStatement s = s("SELECT a,b,c FROM table1 where a = ? UNION select a,b,c from table2 where a = ? UNION select a,b,c FROM table3 where a = ?");
s.setString(1, q);
s.setString(2, q);
s.setString(3, q);
ResultSet r = s.executeQuery();

Я знаю, что это не имеет большого значения, но мне нравится делать вещи эффективными, а также бывают ситуации, когда удобнее читать " + quote(s) + " вместо ?, а затем где-то внизу вы найдете setString .

Ответы [ 4 ]

5 голосов
/ 13 июля 2011

Если вы используете setString для параметра (например, PreparedStatement.setString), вполне может не потребоваться фактическое экранирование - вполне вероятно, что данные будут передаваться отдельно от самого SQL, способом, который не требует побеге.

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

4 голосов
/ 13 июля 2011

Краткий ответ: я бы не стал беспокоиться. Лучше всего бежать в последний момент. Когда вы пытаетесь избежать строки рано и сохранить ее, становится намного сложнее проверить, что все строки были экранированы ровно один раз. (Экранирование строки дважды - это почти так же плохо, как и полное ее отсутствие!) Я видел множество программ, которые пытаются избежать строк рано, а затем сталкиваются с проблемами, потому что им нужно обновить строку, а затем программист забывает повторно выполнить экранирование, или они обновляют экранированную версию строки, или у них есть четыре строки, и они экранируют три из них и т. д. (Я просто работал над ошибкой, когда программист рано делал экранирование HTML на строке, затем решил, что он пришлось урезать строку, чтобы она соответствовала форме, и в итоге пытался вывести строку, которая заканчивалась на «& am». То есть он обрезал свою escape-последовательность, чтобы она больше не действовала.)

Процессорное время для экранирования строки должно быть тривиальным. Если у вас нет очень большого количества записей или очень больших строк, которые используются повторно, я сомневаюсь, что об экономии стоит задуматься. Возможно, вам лучше потратить время на оптимизацию запросов: сохранение чтения одной записи, вероятно, будет стоить гораздо больше, чем устранение 1000 отключений с помощью логики escape-строки.

Более длинный ответ: встроенной функции нет. Вы могли бы написать один достаточно легко: большинству разновидностей SQL нужно просто удвоить любые одинарные кавычки. Возможно, вам также понадобится удвоить обратную косую черту или один или два других специальных символа. Тот факт, что это может отличаться в разных движках SQL, является одним из главных аргументов в пользу использования PreparedStatements и предоставления JDBC возможности беспокоиться об этом. (Лично я думаю, что должна быть функция JDbC для экранирования, которая могла бы знать любые требования, специфичные для механизма БД. Но не так, как есть.)

В любом случае неясно, как это будет работать с PreparedStatement. Должен быть какой-то способ сказать PreparedStatement не экранировать эту строку, потому что она уже экранирована. И кто действительно знает, что происходит под столом в разговоре между JDBC и механизмом БД: возможно, он вообще никогда не избегает этого, а передает его отдельно от запроса. Я полагаю, что в setString может быть дополнительный параметр, который говорит, что «эта строка была предварительно экранирована», но это добавит сложности и потенциальных ошибок при очень небольшом выигрыше.

3 голосов
/ 18 января 2012

Не использовать org.apache.commons.lang.StringEscapeUtils.escapeSql(yourUnscapedSQL);

Он не экранирует символы типа \

1 голос
/ 13 июля 2011

Вы можете использовать StringEscapeUtils из общего достояния Apache:

org.apache.commons.lang.StringEscapeUtils.escapeSql(yourUnscapedSQL);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...