Comme d'autres l'ont indiqué, votre code est fondamentalement correct bien que l'extérieur ne trysoit pas nécessaire. Voici quelques réflexions supplémentaires.
DataSource
D'autres réponses ici sont correctes et bonnes, comme la réponse acceptée par bpgergo. Mais aucun des exemples ne montre l'utilisation de DataSource, généralement recommandée sur l'utilisation de DriverManagerJava moderne.
Par souci d'exhaustivité, voici un exemple complet qui récupère la date actuelle sur le serveur de base de données. La base de données utilisée ici est Postgres . Toute autre base de données fonctionnerait de la même manière. Vous remplaceriez l'utilisation de org.postgresql.ds.PGSimpleDataSourcepar une implémentation DataSourceappropriée à votre base de données. Une implémentation est probablement fournie par votre pilote ou pool de connexions si vous suivez cette voie.
Une DataSourceimplémentation n'a pas besoin d' être fermée, car elle n'est jamais «ouverte». A DataSourcen'est pas une ressource, n'est pas connecté à la base de données, il ne contient donc pas de connexions réseau ni de ressources sur le serveur de base de données. A DataSourceest simplement des informations nécessaires lors de la connexion à la base de données, avec le nom ou l'adresse réseau du serveur de base de données, le nom d'utilisateur, le mot de passe de l'utilisateur et diverses options que vous souhaitez spécifier lorsqu'une connexion est finalement établie. Ainsi, votre DataSourceobjet d'implémentation ne rentre pas dans vos parenthèses try-with-resources.
Try-with-resources imbriqué
Votre code utilise correctement les instructions try-with-resources imbriquées.
Notez dans l'exemple de code ci-dessous que nous utilisons également la syntaxe try-with-resources deux fois , l'une imbriquée dans l'autre. L'extérieur trydéfinit deux ressources: Connectionet PreparedStatement. L'intérieur trydéfinit la ResultSetressource. Il s'agit d'une structure de code commune.
Si une exception est levée depuis l'intérieur, et n'y est pas interceptée, la ResultSetressource sera automatiquement fermée (si elle existe, elle n'est pas nulle). Ensuite, le PreparedStatementsera fermé, et enfin le Connectionsera fermé. Les ressources sont automatiquement fermées dans l'ordre inverse dans lequel elles ont été déclarées dans les instructions try-with-resource.
L'exemple de code ici est trop simpliste. Tel qu'il est écrit, il peut être exécuté avec une seule instruction try-with-resources. Mais dans un vrai travail, vous ferez probablement plus de travail entre la paire d' tryappels imbriqués . Par exemple, vous pouvez extraire des valeurs de votre interface utilisateur ou d'un POJO, puis les transmettre pour remplir les ?espaces réservés dans votre SQL via des appels à des PreparedStatement::set…méthodes.
Notes de syntaxe
Point-virgule de fin
Notez que le point-virgule à la fin de la dernière instruction de ressource entre les parenthèses du try-with-resources est facultatif. Je l'inclus dans mon propre travail pour deux raisons: La cohérence et il semble complet, et cela facilite le copier-coller d'un mélange de lignes sans avoir à se soucier des points-virgules de fin de ligne. Votre IDE peut marquer le dernier point-virgule comme superflu, mais il n'y a aucun mal à le laisser.
Java 9 - Utiliser les variables existantes dans try-with-resources
La nouveauté de Java 9 est une amélioration de la syntaxe try-with-resources. Nous pouvons maintenant déclarer et remplir les ressources en dehors des parenthèses de l' tryinstruction. Je n'ai pas encore trouvé cela utile pour les ressources JDBC, mais gardez cela à l'esprit dans votre propre travail.
ResultSet devrait se fermer, mais ne peut pas
Dans un monde idéal, le ResultSetse fermerait comme le promet la documentation:
Un objet ResultSet est automatiquement fermé lorsque l'objet Statement qui l'a généré est fermé, réexécuté ou utilisé pour récupérer le résultat suivant d'une séquence de résultats multiples.
Malheureusement, dans le passé, certains pilotes JDBC n'ont pas tenu cette promesse. En conséquence, de nombreux programmeurs JDBC ont appris à fermer explicitement toutes leurs ressources JDBC , y compris Connection, PreparedStatementet ResultSetaussi. La syntaxe moderne try-with-resources a rendu cela plus facile et avec un code plus compact. Notez que l'équipe Java s'est donnée la peine de marquer ResultSetcomme AutoCloseable, et je suggère que nous nous en servions. L'utilisation d'un essai avec des ressources autour de toutes vos ressources JDBC rend votre code plus auto-documenté quant à vos intentions.
Exemple de code
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()) {car un objet ResultSet est automatiquement fermé par l'objet Statement qui l'a généré