Неявные попытки использования Java-ресурсов
Мне интересно, правильно ли использует следующий код try-with-resources.
try (ResultSet rs = new QueryBuilder(connection, tableName(), getPaths(), searchQuery()).add(constraint).build().executeQuery()) {
while (rs.next()) {
beans.add(createBean(rs));
}
}
Аргументы не важны, важно только:
-
new QueryBuilder().build();
возвращает a PreparedStatement
.
Я полностью понимаю, что rs
будет закрыто, но также будет закрыто PreparedStatement
, и если да, то по какой причине? Поскольку ResultSet
закрывается или из-за попыток с ресурсами?
Ответы
Ответ 1
PreparedStatement # close() автоматически закроет любые связанные результирующие множества, но обратное не является истинным, поскольку операторы повторно используются после того, как их результирующие наборы замкнутый.
Посмотрите на javadoc ResultSet # закрыть():
Примечание. Объект ResultSet автоматически закрывается объектом Statement, который сгенерировал его, когда этот объект Statement закрыт
И затем Statement # close():
Примечание. Когда объект Statement закрыт, его текущий объект ResultSet, если он существует, также закрыт.
Это использование выглядит очень дрянной для меня:
ResultSet rs=conn.createStatement().executeQuery();
Если выполняется достаточно много раз, это приведет к утечке всех доступных курсоров, поскольку курсоры связаны с Statement
не с ResultSet
.
Следовательно, чтобы закрыть базовый PreparedStatement
с помощью try-with-resources statement, просто объявите его в инструкции try
:
Оператор try-with-resources параметризуется переменными (известными как ресурсы), которые инициализируются перед исполнением блока try и автоматически закрываются.
Посмотрите этот ответ из assylias, объявите PreparedStatement
, а также ResultSet
внутри оператора try
.
Так как вы не ищете утечку памяти , а утечку ресурса. Память PreparedStatement
будет собрана в конечном итоге и освободится память, так как она больше не упоминается после выполнения вашего метода с учетом способа ее инициализации, однако ресурсы, хранящиеся в Statement
, не закрыты.
Ответ 2
В попытке можно добавить несколько ресурсов, и все они будут закрыты, что необходимо, если вы хотите закрыть PreparedStatement
:
try (PreparedStatement ps = new QueryBuilder(connection, tableName(), getPaths(), searchQuery()).add(constraint).build();
ResultSet rs = ps.executeQuery();) {
while (rs.next()) {
beans.add(createBean(rs));
}
}
Ответ 3
В соответствии с документацией здесь - tryResourceClose, как я ее прочитал, он специфичен для ресурсов declared
.
The try-with-resources statement is a try statement that declares one or more resources.
Читайте ниже:
You may declare one or more resources in a try-with-resources statement. The following example retrieves the names of the files packaged in the zip file zipFileName and creates a text file that contains the names of these files:
try (
java.util.zip.ZipFile zf =
new java.util.zip.ZipFile(zipFileName);
java.io.BufferedWriter writer =
java.nio.file.Files.newBufferedWriter(outputFilePath, charset)
) {
Я предлагаю вам правильный ответ:
try{
PreparedStatement statement = new QueryBuilder(connection, tableName(), getPaths(), searchQuery())
.add(constraint).build();
ResultSet rs = statement.executeQuery())
}
Ответ 4
Как вы правильно сказали, rs
будет закрыто. Это означает, что метод close()
будет вызываться на rs
. Таким образом, оператор try-with-ressource явно не закрывает PreparedStatement
в вашем случае.
Если он закрыт иначе (в контексте rs.close()
), трудно сказать, не зная реализации; -)
ИЗМЕНИТЬ
Как правильно выяснил @NewIdiot, ваш PreparedStatement
не будет закрыт.