Wie andere gesagt haben, ist Ihr Code grundsätzlich korrekt, obwohl der äußere try
nicht 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 DriverManager
in 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.PGSimpleDataSource
durch eine Implementierung ersetzen, die DataSource
Ihrer Datenbank entspricht. Eine Implementierung wird wahrscheinlich von Ihrem bestimmten Treiber oder Verbindungspool bereitgestellt, wenn Sie diesen Weg gehen.
Eine DataSource
Implementierung muss nicht geschlossen werden, da sie niemals „geöffnet“ wird. A DataSource
ist keine Ressource, ist nicht mit der Datenbank verbunden und enthält daher weder Netzwerkverbindungen noch Ressourcen auf dem Datenbankserver. A DataSource
sind 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 DataSource
Implementierungsobjekt 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 try
definiert zwei Ressourcen: Connection
und PreparedStatement
. Das Innere try
definiert die ResultSet
Ressource. Dies ist eine gängige Codestruktur.
Wenn eine Ausnahme von der inneren ausgelöst und dort nicht abgefangen wird, wird die ResultSet
Ressource automatisch geschlossen (falls vorhanden, ist sie nicht null). Danach PreparedStatement
wird das geschlossen und zuletzt das Connection
geschlossen. 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 try
erledigen. 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 try
Anweisung 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 ResultSet
wü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
, PreparedStatement
und ResultSet
auch. 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, ResultSet
als 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