2016-01-02 2 views
6

Предположим, у нас есть класс, который записывает в базу данных сообщение журнала. Этот класс вызывается из разных частей кода и выполняет снова и снова тот же оператор INSERT. Кажется, что он призывает использовать PreparedStatement.Правильное использование PreparedStatement

Однако мне интересно, что это за правильное использование. Я все еще получаю выгоду от его использования, например, СУБД, используя один и тот же путь выполнения каждый раз, когда он выполняется, даже если я создаю новый PreparedStatement каждый раз при вызове метода или должен ли я иметь PreparedStatement как член класса и никогда не закрывать это для того, чтобы использовать его и получать от этого выгоду?

Теперь, если единственный способ получить выгоду с помощью PreparedStatement в этом случае состоит в том, чтобы сохранить его открытым как член класса, может ли одно и то же соединение одновременно открывать разные подготовленные (с разными запросами) PreparedStatement? Что происходит, когда два из этих PreparedStatements выполняются одновременно? Проверяет ли драйвер JDBC выполнение PreparedStatements?

Заранее спасибо, Dani.

+2

Это зависит от используемой СУБД. Некоторые из них (автоматически) кэшируют планы выполнения на сервере, а некоторые нет. Некоторые кешируют планы в драйвере, некоторые не делают –

+0

В дополнение к предыдущему комментарию, промежуточное программное обеспечение также может кэшировать операторы (например, серверы приложений). –

+1

Соединения JDBC, как правило, не являются потокобезопасными, поэтому вы не должны одновременно запускать два PreparedStatements (из разных потоков) в одном и том же соединении. Если вы попробуете, вы получите странные ошибки. – Jesper

ответ

3

Для всех, кого я знаю и опытных, операторы не работают параллельно по одному соединению. И как вы правильно заметили, PreparedStatement s связаны с Connection, на которых они были созданы.

Поскольку вы, вероятно, не хотите синхронизировать свой вход в систему (одна вставка одновременно с блокировкой накладных расходов), вам необходимо сохранить соединения, зарезервированные для этого оператора ведения журнала.

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

Итак, какие варианты остались?

  • подготовить инструкцию для каждой вставки. Поскольку у вас будут операции ввода-вывода для отправки данных в db, накладные расходы на подготовку относительно малы.

  • подготовить заявление в вашем пуле при создании нового соединения и построить Map <Connection,PreparedStatement> для ссылки на них позже. Делает новые соединения немного медленнее, но позволяет переработать инструкцию.

  • Использование некоторого асинхронный пути в очереди журналы (JMS) и делать Insert в пакете внутри сообщения ведомых боба или аналогичном

Вероятно, еще несколько вариантов - но это все, что я мог думать прямо сейчас ,

Удачи вам в этом.

+0

Привет, Ян. Tks за ваш ответ.Я думаю, что я буду придерживаться вашего первого варианта, одного PreparedStatement для каждого вызова (моя текущая реализация), просто я не вижу необходимости в PreparedStatement. Я чувствую, что выполнение всего запроса в простом Заявлении должно быть быстрее. Если СУБД кэширует PreparedStatement, он также должен кэшировать как-то повторяющиеся утверждения. –

+0

Совсем наоборот. Если вы поместите свои значения в строку, оператор никогда не повторится. Что это будет делать с использованием переменных привязки (= PreparedStatement) Не говоря уже о SQLInjection, который может произойти, если вы «регистрируете» строки из-за пределов приложения – Jan

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