Wie andere gesagt haben, ist Ihr Code grundsätzlich korrekt, obwohl der äußere trynicht benötigt wird. Hier noch ein paar Gedanken.
DataSource
Andere Antworten hier sind richtig und gut, wie die akzeptierte Antwort von bpgergo. Aber keine der Shows zeigt die Verwendung von DataSource, allgemein empfohlen gegenüber der Verwendung DriverManagerin modernem Java.
Der Vollständigkeit halber finden Sie hier ein vollständiges Beispiel, das das aktuelle Datum vom Datenbankserver abruft. Die hier verwendete Datenbank ist Postgres . Jede andere Datenbank würde ähnlich funktionieren. Sie würden die Verwendung von org.postgresql.ds.PGSimpleDataSourcedurch eine Implementierung ersetzen, die DataSourceIhrer Datenbank entspricht. Eine Implementierung wird wahrscheinlich von Ihrem bestimmten Treiber oder Verbindungspool bereitgestellt, wenn Sie diesen Weg gehen.
Eine DataSourceImplementierung muss nicht geschlossen werden, da sie niemals „geöffnet“ wird. A DataSourceist keine Ressource, ist nicht mit der Datenbank verbunden und enthält daher weder Netzwerkverbindungen noch Ressourcen auf dem Datenbankserver. A DataSourcesind lediglich Informationen, die beim Herstellen einer Verbindung zur Datenbank benötigt werden, mit dem Netzwerknamen oder der Netzwerkadresse des Datenbankservers, dem Benutzernamen, dem Benutzerkennwort und verschiedenen Optionen, die angegeben werden sollen, wenn eine Verbindung hergestellt wird. Ihr DataSourceImplementierungsobjekt wird also nicht in die Klammern für den Versuch mit Ressourcen eingefügt.
Verschachtelter Versuch mit Ressourcen
Ihr Code verwendet verschachtelte Try-with-Resources-Anweisungen ordnungsgemäß.
Beachten Sie im folgenden Beispielcode, dass wir die Try-with-Resources-Syntax auch zweimal verwenden , wobei eine in die andere verschachtelt ist. Das Äußere trydefiniert zwei Ressourcen: Connectionund PreparedStatement. Das Innere trydefiniert die ResultSetRessource. Dies ist eine gängige Codestruktur.
Wenn eine Ausnahme von der inneren ausgelöst und dort nicht abgefangen wird, wird die ResultSetRessource automatisch geschlossen (falls vorhanden, ist sie nicht null). Danach PreparedStatementwird das geschlossen und zuletzt das Connectiongeschlossen. Ressourcen werden automatisch in umgekehrter Reihenfolge geschlossen, in der sie in den Anweisungen zum Ausprobieren mit Ressourcen deklariert wurden.
Der Beispielcode hier ist zu simpel. Wie geschrieben, kann es mit einer einzelnen Try-with-Resources-Anweisung ausgeführt werden. Aber in einer echten Arbeit werden Sie wahrscheinlich mehr Arbeit zwischen den verschachtelten Anrufpaaren tryerledigen. Beispielsweise extrahieren Sie möglicherweise Werte von Ihrer Benutzeroberfläche oder einem POJO und übergeben diese dann, um ?Platzhalter in Ihrem SQL über Aufrufe von PreparedStatement::set…Methoden zu erfüllen .
Syntaxnotizen
Nachfolgendes Semikolon
Beachten Sie, dass das Semikolon hinter der letzten Ressourcenanweisung in den Klammern des Versuchs mit Ressourcen optional ist. Ich nehme es aus zwei Gründen in meine eigene Arbeit auf: Konsistenz und es sieht vollständig aus und erleichtert das Kopieren und Einfügen einer Mischung von Zeilen, ohne sich um Semikolons am Zeilenende kümmern zu müssen. Ihre IDE kennzeichnet das letzte Semikolon möglicherweise als überflüssig, aber es schadet nicht, es zu verlassen.
Java 9 - Verwenden Sie vorhandene Variablen in Try-with-Resources
Neu in Java 9 ist eine Erweiterung der Syntax zum Ausprobieren von Ressourcen. Wir können jetzt die Ressourcen außerhalb der Klammern der tryAnweisung deklarieren und füllen . Ich habe dies noch nicht für JDBC-Ressourcen nützlich gefunden, aber denken Sie bei Ihrer eigenen Arbeit daran.
ResultSet sollte sich schließen, darf aber nicht
In einer idealen Welt ResultSetwürde sich das schließen, wie die Dokumentation verspricht:
Ein ResultSet-Objekt wird automatisch geschlossen, wenn das Anweisungsobjekt, das es generiert hat, geschlossen, erneut ausgeführt oder zum Abrufen des nächsten Ergebnisses aus einer Folge mehrerer Ergebnisse verwendet wird.
Leider haben in der Vergangenheit einige JDBC-Fahrer dieses Versprechen nicht erfüllt. Viele JDBC - Programmierer gelernt explizit schließen alle JDBC - Ressourcen , einschließlich Als Ergebnis Connection, PreparedStatementund ResultSetauch. Die moderne Try-with-Resources-Syntax hat dies einfacher und mit kompakterem Code gemacht. Beachten Sie, dass sich das Java-Team die Mühe gemacht hat, ResultSetals zu markieren AutoCloseable, und ich schlage vor, dass wir davon Gebrauch machen. Durch die Verwendung eines Try-with-Resources für alle Ihre JDBC-Ressourcen wird Ihr Code in Bezug auf Ihre Absichten selbstdokumentierender.
Codebeispiel
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()) {da ein ResultSet-Objekt automatisch von dem Statement-Objekt geschlossen wird, das es generiert hat