2011-01-10 3 views
6

Мы все knowthat Мы должны скорее использовать JDBC PreparedStatement, чем создавать новый экземпляр внутри цикла.Повторное использование подготовленного состояния между методами?

Но как бороться с PreparedStatement повторного использования между различными вызовами метода? До сих пор считается, что правило повторного использования?

Должен ли я использовать поле для PreparedStatement, или мне нужно закрыть и заново создать подготовленный оператор в каждом вызове (сохранить его локально)? (Конечно, экземпляр такого класса будет связан с Connection, который может быть недостатком в некоторых архитектурах)

Я знаю, что идеальным ответом может быть «это зависит».
Но я ищу оптимальную практику для менее опытных разработчиков, чтобы они сделали правильный выбор в большинстве случаев.

+3

Определенно не делайте это полем класса. Сохраните метод methodlocal. – BalusC

ответ

13

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

Может быть? это был бы огромный недостаток. Вам нужно будет либо синхронизировать с ним доступ, что бы убить вашу многопользовательскую производительность с мертвой точки или создать несколько экземпляров и сохранить их в пуле. Основная боль в заднице.

Задание пула - это работа драйвера JDBC, и большинство, если не все, текущего урожая драйверов делают это за вас. Когда вы вызываете prepareStatement или prepareCall, драйвер будет обрабатывать повторное использование существующих ресурсов и предварительно скомпилированных операторов.

Statement объекты привязаны к соединению, и соединения должны использоваться и возвращаться в бассейн как можно быстрее.

Короче говоря, стандартная практика получения PreparedStatement в начале метода, используя его повторно в течение цикла, а затем закрыть его в конце метода, является лучшей практики.

+0

Я не понимаю, почему это большое дело. У вас есть один поток за соединение. Каждый класс обслуживания (содержащий ваши методы CRUD) создает PreparedStatements вверх и повторно использует их во всех методах. PreparedStatements закрываются, когда соединение закрывается. – Gili

0

Да, его можно использовать повторно, но я считаю, что это считается только если используется тот же объект Connection, и если вы используете пул соединений с базой данных (например, из веб-приложения), то объекты Connection будут потенциально разный каждый раз.

Я всегда воссоздаю PreparedStatement перед каждым использованием в веб-приложении по этой причине.

Если вы не используете пул подключений, тогда вы являетесь золотым!

0

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

+1

Поскольку PreparedStatement «принадлежит» определенному соединению, вы просто не можете его повторно использовать в разных соединениях. Конечно, вы можете повторно использовать код, который будет выполняться по разным Соединениям, но хорошая вещь о PreparedStatment заключается в том, чтобы оставить его подготовленным один раз и повторно использовать его, что невозможно, если вы используете другое соединение. –

6

Многие рабочие нагрузки базы данных связаны с процессором, а не связаны с IO. Это означает, что база данных в конечном итоге тратит больше времени на выполнение такой работы, как анализ SQL-запросов и выяснение способов их обработки (выполнение «плана выполнения»), чем при доступе к диску.Это скорее относится к транзакционным нагрузкам, чем к «отчетным» рабочим нагрузкам, но в обоих случаях время, затрачиваемое на подготовку плана, может быть больше, чем вы ожидаете.

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

Некоторые драйверы JDBC и/или пулы соединений предлагают прозрачное «кэширование рецептов», так что вам не нужно делать это самостоятельно. До тех пор, пока вы понимаете поведение вашей конкретной выбранной стратегии прозрачного кэширования, прекрасно держать ее в курсе событий ... то, чего вы действительно хотите избежать, - это попадание в базу данных.

+0

Существует множество разумных запросов, которые потребуют большого количества ввода-вывода в базе данных. В частности, все, что делает вычисления/агрегации/... больших наборов данных. –

+0

@Jochaim Sauer: Я определил свои опрометчивые утверждения :-) –