Вы должны закрыть все, что вы открываете. Когда вы создаете подготовленный оператор или набор результатов, база данных выделяет ресурсы для них, и закрытие их указывает базе данных освободить эти ресурсы (вероятно, база данных будет перераспределять эти ресурсы в конце концов по истечении времени ожидания, но вызов close позволяет базе данных знать, что она может идти вперед и убирать). Ваш второй пример лучше, за исключением того, что я бы закрыл набор результатов перед подготовленным оператором.
Таким образом, при включении блоков try это будет выглядеть так:
while (...){
PreparedStatement p = connection.prepareStatement(...);
try {
ResultSet r = p.executeQuery();
try {
while (r.next()) {
....
}
} finally {
try {
r.close();
} catch (SQLException e) {
// log this or something -- prevent these from masking original exception
}
}
}
finally {
try {
p.close();
} catch (SQLException e) {
// log this or something -- prevent these from masking original exception
}
}
}
Захватывать исключения из закрытия ужасно, но если у вас возникло исключение во время выполнения подготовленного оператора или во время обхода результирующего набора, вы хотите убедиться, что вы видите его, а не исключение, которое выдается при закрытие подготовленного оператора или набора результатов (что связано с некоторым сетевым сбоем, с которым вы все равно ничего не можете сделать).
Также имейте в виду, что использование try-with-resources будет работать, за исключением того, что если у вас есть случай, когда операция с базой данных завершается успешно, но вызов close приводит к исключению, то исключение будет выдано.
Я рекомендую людям использовать библиотеку spring-jdbc (которая обрабатывает закрытие всего для вас) вместо того, чтобы вручную запускать iffy или verbose jdbc.