2014-07-07 3 views
1

Я написал универсальный слой DAO для mySQL (он может сохранить \ получить любой объект класса, который расширяет Entity до \ из таблицы с помощью Reflection и ResultSetMetaData). Моя реализация имеет небольшую конкатенацию в sql-запросе. Разве это не все преимущества подготовленного заявления, или я просто теряю мало возможностей для concat String и не более того?Конкатенация в подготовленном сообщении

Например, кусок кода для объекта удаления:

PreparedStatement prepStatement = con.prepareStatement("DELETE FROM " 
             + tableName + " WHERE id = ?"); 
prepStatement.setLong(1, id); 
+3

Разве это не все преимущества подготовленного заявления? Нет, это не так. Читать [Когда мы используем PreparedStatement вместо Statement?] (Http://stackoverflow.com/questions/2099425/when-we-use-preparedstatement-instead-of-statement) и Read [когда использовать StringBuilder в java] (http : //stackoverflow.com/questions/4645020/when-to-use-stringbuilder-in-java) – Braj

+0

Я знаю о StringBuilder и об этом преимуществах над конкатенацией строк.В случае добавления только имени таблицы я думаю, что StringBuilder избыточен. –

+0

Ответ на ваш вопрос в первой ссылке. Второй - только предложение. – Braj

ответ

3

Основное преимущество PreparedStatement с, когда у вас есть код, который ведет себя подобным образом к этому псевдокоде:

PreparedStatement ps = con.prepareStatement("blabalblabla"); 
for (int i = 0; i < a gazillion times; i++) { 
    // Set parameters into ps 
    ... 
    // execute already prepared statement 
    ps.execute(); 
} 

То есть , вы готовите один раз и выполняете много раз, каждый раз с различными наборами параметров. Это позволяет драйверу/базе данных выполнять потенциально дорогостоящие операции (например, синтаксический анализ) только один раз, а затем повторно использовать эту работу. Кроме того, использование PreparedStatement может быть интерпретировано как подсказка для драйвера о том, что он должен кэшировать эти ресурсы инструкций или что-то, потому что он будет использоваться позже, но я не думаю, что это будет иметь такое же влияние, как «подготовить один раз выполнить многие «подходы».

Ваше использование конкатенации для добавления имен таблиц не приведет к отключению оптимизаций, которые делает ваш драйвер JDBC (если есть). Но в любом случае, если ваш код делает больше «подготовить один раз выполнить один раз», чем он «готовит один раз выполнить многие», то PreparedStatement может иметь только незначительное преимущество в производительности.

Обратите внимание, что все вышеперечисленное отличается высокой базой данных/драйвером. Например, Oracle выполняет много лучше, если вы используете PreparedStatement s так, как я описал как «подготовить один раз выполнить многие». И как последний совет, не забывайте, что вам следует избегать конкатенации значений параметров, если у вас нет другого варианта, как для производительности, так и для целей И БЕЗОПАСНОСТИ.

+0

Итак, мои предложения были верны. Драйвер JDBC после первого вызова метода с новым именем таблицы будет кэшировать новый подготовленный оператор, и все последующие вызовы с этим объектом будут использовать старый подготовленный оператор. –

+0

Нет, вам нужно проверить документацию/исходный код, что действительно делает ваш JDBC-драйвер и комбинация баз данных в отношении 'PreparedStatement'. То, что я описал, - это то, что может сделать разумная комбинация JDBC-драйвера/базы данных *. – gpeche

0

Переменная tableName в вашем примере может ввести уязвимость для SQL-инъекции, но это могут быть альтернативные способы защиты от этого. Например,

Map<String,String> myTables; // key and value are the same. 
tableName = myTables.get(tableName); // safe known value or null. 

Как правило, лучше всего использовать подготовленные заявления, чтобы избежать неприятностей. Однако иногда создание запроса (чаще всего where запрос) «на лету» может сэкономить много строк, в противном случае близких к дублируемому коду, поэтому трудно сказать «никогда не делай этого».

+0

Да, я забочусь о tableName с ключевым словом «final» :-) –

1

Рекомендуется использовать подготовленные операторы для улучшения производительности БД. Теоретически драйверы БД кэшируют подготовленные операторы (возможно, вам потребуется включить кеширование на объект соединения). Я бы предположил, что конкатенация не так критична. Имейте в виду, что имя таблицы может быть чувствительным к регистру в кеше драйвера.

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

Смежные вопросы