Come altri hanno affermato, il tuo codice è sostanzialmente corretto anche se l'esterno try
non è necessario. Ecco qualche altro pensiero.
DataSource
Altre risposte qui sono corrette e buone, come la risposta accettata da bpgergo. Ma nessuno dei programmi mostra l'uso DataSource
, comunemente raccomandato rispetto all'uso DriverManager
nella moderna Java.
Quindi, per completezza, ecco un esempio completo che recupera la data corrente dal server di database. Il database utilizzato qui è Postgres . Qualsiasi altro database funzionerebbe in modo simile. Sostituiresti l'uso di org.postgresql.ds.PGSimpleDataSource
con un'implementazione di DataSource
appropriate al tuo database. Un'implementazione è probabilmente fornita dal tuo driver specifico o dal pool di connessioni se segui quel percorso.
DataSource
Un'implementazione deve non essere chiuso, perché non è mai “aperto”. A DataSource
non è una risorsa, non è connessa al database, quindi non contiene connessioni di rete né risorse sul server di database. A DataSource
sono semplicemente le informazioni necessarie quando si effettua una connessione al database, con il nome o l'indirizzo di rete del server di database, il nome utente, la password utente e le varie opzioni che si desidera specificare quando viene stabilita una connessione. Quindi l' DataSource
oggetto di implementazione non rientra nelle parentesi di prova con risorse.
Prova con risorse nidificata
Il codice utilizza correttamente le istruzioni nidificate di prova con risorse.
Si noti nel seguente codice di esempio che utilizziamo anche la sintassi try-with-resources due volte , una nidificata all'interno dell'altra. L'esterno try
definisce due risorse: Connection
e PreparedStatement
. L'interno try
definisce la ResultSet
risorsa. Questa è una struttura di codice comune.
Se viene generata un'eccezione da quella interna e non rilevata lì, la ResultSet
risorsa verrà automaticamente chiusa (se esiste, non è nulla). Successivamente, PreparedStatement
verrà chiuso e infine Connection
verrà chiuso. Le risorse vengono automaticamente chiuse in ordine inverso rispetto a quanto dichiarato nelle istruzioni di prova con risorsa.
Il codice di esempio qui è eccessivamente semplicistico. Come scritto, potrebbe essere eseguito con una singola istruzione try-with-resources. Ma in un vero lavoro probabilmente farai più lavoro tra la coppia nidificata di try
chiamate. Ad esempio, potresti estrarre valori dall'interfaccia utente o da un POJO e quindi passarli per soddisfare i ?
segnaposto all'interno di SQL tramite chiamate ai PreparedStatement::set…
metodi.
Note di sintassi
Punto e virgola finale
Si noti che il punto e virgola che segue l'ultima istruzione di risorsa tra parentesi delle risorse di prova è facoltativo. Lo includo nel mio lavoro per due motivi: coerenza e aspetto completo, e rende più semplice incollare un mix di linee senza doversi preoccupare dei punti e virgola di fine riga. Il tuo IDE può contrassegnare l'ultimo punto e virgola come superfluo, ma non c'è nulla di male nel lasciarlo.
Java 9 - Usa i var esistenti in try-with-resources
Novità di Java 9 è un miglioramento della sintassi di prova con risorse. Ora possiamo dichiarare e popolare le risorse al di fuori delle parentesi try
dell'istruzione. Non l'ho ancora trovato utile per le risorse JDBC, ma tienilo a mente nel tuo lavoro.
ResultSet
dovrebbe chiudersi, ma potrebbe non esserlo
In un mondo ideale ResultSet
si chiuderebbe come promette la documentazione:
Un oggetto ResultSet viene automaticamente chiuso quando l'oggetto Statement che lo ha generato viene chiuso, rieseguito o utilizzato per recuperare il risultato successivo da una sequenza di più risultati.
Sfortunatamente, in passato alcuni driver JDBC non sono riusciti a mantenere questa promessa. Come risultato, molti programmatori JDBC imparato a esplicitamente vicino tutte le loro risorse JDBC, tra cui Connection
, PreparedStatement
e ResultSet
troppo. La moderna sintassi di prova con risorse ha reso tutto più semplice e con un codice più compatto. Si noti che il team Java si è preso la briga di contrassegnare ResultSet
come AutoCloseable
, e suggerisco di usarlo. L'uso di una prova con le risorse intorno a tutte le risorse JDBC rende il codice più autocompattante delle tue intenzioni.
Esempio di codice
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()) {
perché un oggetto ResultSet viene automaticamente chiuso dall'oggetto Statement che lo ha generato