Як зазначають інші, ваш код в основному правильний, хоча зовнішній tryвигляд непотрібний. Ось ще кілька думок.
DataSource
Інші відповіді тут правильні і хороші, такий прийнятий Відповідь від bpgergo. Але жоден з них не показує використання DataSource, як правило, рекомендується над використанням DriverManagerсучасних Java.
Отже, для повноти, ось повний приклад, який отримує поточну дату з сервера баз даних. Тут використовується база даних Postgres . Будь-яка інша база даних буде працювати аналогічно. Ви б замінили використання org.postgresql.ds.PGSimpleDataSourceна реалізацію, DataSourceвідповідну вашій базі даних. Реалізація, ймовірно, надається вашим конкретним драйвером або пулом з'єднань, якщо ви йдете цим маршрутом.
DataSourceРеалізації потрібні НЕ бути закриті, тому що вона ніколи не «відкрито». A DataSourceне є ресурсом, не підключений до бази даних, тому він не містить мережевих з'єднань, ані ресурсів на сервері баз даних. A DataSource- це просто інформація, необхідна під час встановлення з'єднання з базою даних, з мережевим іменем або адресою сервера бази даних, ім'ям користувача, паролем користувача та різними параметрами, які ви хочете вказати, коли з часом встановлено з'єднання. Таким чином, DataSourceоб’єкт реалізації не заходить у ваші круглі дужки пробних ресурсів.
Вкладені пробні ресурси
Ваш код належним чином використовує вкладені заяви про тестування ресурсів.
Зауважте в наведеному нижче прикладі коду, що ми також двічі використовуємо синтаксис спробу використання ресурсів , один вкладений всередині іншого. Зовнішній tryвизначає два ресурси: Connectionі PreparedStatement. Внутрішня tryвизначає ResultSetресурс. Це загальна структура коду.
Якщо виняток буде викинуто з внутрішнього і не потрапив туди, ResultSetресурс автоматично закриється (якщо він існує, не є нульовим). Після цього PreparedStatementзаповіт буде закритий, і нарешті Connection, закритий. Ресурси автоматично закриваються в зворотному порядку, в якому вони були задекларовані в операторах спробування ресурсів.
Приклад коду тут надмірно спрощений. Як написано, це може бути виконано за допомогою одного оператора "спробу використання ресурсів". Але в реальній роботі ви, ймовірно, будете робити більше роботи між вкладеною парою tryдзвінків. Наприклад, ви можете витягувати значення з інтерфейсу користувача або POJO, а потім передавати їх на виконання ?заповнювачів у вашому SQL за допомогою викликів PreparedStatement::set…методів.
Синтаксичні нотатки
Зворотна крапка з комою
Зауважте, що крапка з комою, що відкладає останню заяву про ресурси, в дужках спробувати-ресурси - необов’язкова. Я включаю його до своєї роботи з двох причин: Послідовність і вона виглядає повноцінною, і це полегшує копіювання суміші рядків легше, не турбуючись про крапки з комою крапки. Ваш IDE може позначити останню крапку з комою як зайву, але немає шкоди, залишаючи її.
Java 9 - Використовуйте наявні VARS у спробах використання ресурсів
Нове в Java 9 - це вдосконалення синтаксису "пробних ресурсів". Тепер ми можемо оголошувати та заповнювати ресурси поза дужками tryзаяви. Я ще не знайшов цього корисного для ресурсів JDBC, але пам’ятайте про це у власній роботі.
ResultSet повинен закрити себе, а може і не
В ідеальному світі це ResultSetзакриється, як обіцяє документація:
Об'єкт ResultSet автоматично закривається, коли об'єкт заяви, який його створив, закривається, повторно виконується або використовується для отримання наступного результату з послідовності декількох результатів.
На жаль, у минулому деякі водії JDBC ганебно не виконали цієї обіцянки. В результаті, багато програмістів JDBC навчилися явно закрити всі свої ресурси , включаючи JDBC Connection, PreparedStatementі ResultSetтеж. Сучасний синтаксис "пробних ресурсів" зробив це простіше і з більш компактним кодом. Зауважте, що команда Java набридла відзначати ResultSetяк AutoCloseable, і я пропоную скористатися цим. Використання пробних ресурсів навколо всіх ваших ресурсів JDBC робить ваш код більш самодокументованим щодо ваших намірів.
Приклад коду
package work.basil.example;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.LocalDate;
import java.util.Objects;
public class App
{
public static void main ( String[] args )
{
App app = new App();
app.doIt();
}
private void doIt ( )
{
System.out.println( "Hello World!" );
org.postgresql.ds.PGSimpleDataSource dataSource = new org.postgresql.ds.PGSimpleDataSource();
dataSource.setServerName( "1.2.3.4" );
dataSource.setPortNumber( 5432 );
dataSource.setDatabaseName( "example_db_" );
dataSource.setUser( "scott" );
dataSource.setPassword( "tiger" );
dataSource.setApplicationName( "ExampleApp" );
System.out.println( "INFO - Attempting to connect to database: " );
if ( Objects.nonNull( dataSource ) )
{
String sql = "SELECT CURRENT_DATE ;";
try (
Connection conn = dataSource.getConnection() ;
PreparedStatement ps = conn.prepareStatement( sql ) ;
)
{
… make `PreparedStatement::set…` calls here.
try (
ResultSet rs = ps.executeQuery() ;
)
{
if ( rs.next() )
{
LocalDate ld = rs.getObject( 1 , LocalDate.class );
System.out.println( "INFO - date is " + ld );
}
}
}
catch ( SQLException e )
{
e.printStackTrace();
}
}
System.out.println( "INFO - all done." );
}
}
try (ResultSet rs = ps.executeQuery()) {оскільки об'єкт ResultSet автоматично закривається об'єктом Statement, який його генерував