Я не помню, чтобы Hibernate действительно сохранял экземпляры PreparedStatement сам или полагался на то, что провайдер соединений использует их повторно. (Быстрое сканирование BatcherImpl предполагает, что он повторно использует последний PreparedStatement при выполнении одного и того же SQL несколько раз подряд)
Я думаю, что документация c3p0 пытается подчеркнуть, что для многих драйверов JDBC PreparedStatement бесполезен: некоторые драйверы в конечном итоге просто объединяют параметры на стороне клиента и затем передают встроенный оператор SQL в база данных в любом случае. Для этих драйверов PreparedStatements не имеют никакого преимущества, и любые попытки их повторного использования напрасны. (В Postgresql JDBC FAQ сказано, что это имело место в Postgresql до версии 3 протокола протокола, и более подробную информацию можно найти в документации ).
Для драйверов, которые обрабатывают PreparedStatements с пользой, все же, вероятно, необходимо фактически использовать экземпляры PreparedStatement, чтобы получить какую-либо выгоду. Например, если драйвер реализует:
- Connection.prepareStatement (sql) - создать оператор на стороне сервера
- PreparedStatement.execute (..) и т. Д. - выполнить этот оператор на стороне сервера
- PreparedStatement.close () - освободить серверную инструкцию
Учитывая это, если приложение всегда открывает подготовленный оператор, выполняет его один раз, а затем снова закрывает, все равно не принесет никакой пользы; на самом деле, это могло бы быть и хуже, так как в настоящее время потенциально больше поездок туда и обратно. Таким образом, приложение должно держаться за экземпляры PreparedStatement. Конечно, это приводит к другой проблеме: если приложение слишком сильно зависает, и каждый оператор на стороне сервера потребляет некоторые ресурсы, это может привести к проблемам на стороне сервера. В случае, когда кто-то использует JDBC напрямую, этим можно управлять вручную - некоторые операторы, как известно, могут быть использованы повторно и, следовательно, подготовлены; некоторые нет, и вместо этого просто используют временные экземпляры Statement. (Это пропускает другое преимущество готовых операторов: обработка аргумента, экранирующего)
Вот почему c3p0 и другие пулы соединений также имеют подготовленные кеши операторов - это позволяет коду приложения избегать всего этого. Операторы обычно хранятся в каком-то ограниченном пуле LRU, поэтому общие операторы повторно используют экземпляр PreparedStatement.
Последними частями головоломки являются то, что драйверы JDBC сами могут решить быть умными и сделать это; и сами серверы могут также решить быть хитрыми и обнаружить клиента, отправляющего заявление, которое структурно аналогично предыдущему.
Учитывая, что Hibernate сам не хранит кэш экземпляров PreparedStatement, вам нужно сделать так, чтобы c3p0 использовал их. (Которые должны быть уменьшены накладные расходы для общих операторов из-за повторного использования кэшированных планов). Если c3p0 не кэширует подготовленные операторы, то драйвер просто увидит, как приложение готовит оператор, выполняет его, а затем снова закрывает. Похоже, что драйвер JDBC имеет настройку «порогового значения» для избежания нагрузки на сервер подготовки / выполнения в случае, когда приложение всегда делает это. Итак, да, вам нужно иметь кеширование операторов c3p0 do.
Надеюсь, это поможет, извините, это немного затянуто. Ответ да .