Comme d'autres l'ont indiqué, votre code est fondamentalement correct bien que l'extérieur ne try
soit 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 DriverManager
Java 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.PGSimpleDataSource
par une implémentation DataSource
approprié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 DataSource
implémentation n'a pas besoin d' être fermée, car elle n'est jamais «ouverte». A DataSource
n'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 DataSource
est 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 DataSource
objet 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 try
définit deux ressources: Connection
et PreparedStatement
. L'intérieur try
définit la ResultSet
ressource. 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 ResultSet
ressource sera automatiquement fermée (si elle existe, elle n'est pas nulle). Ensuite, le PreparedStatement
sera fermé, et enfin le Connection
sera 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' try
appels 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' try
instruction. 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 ResultSet
se 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
, PreparedStatement
et ResultSet
aussi. 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 ResultSet
comme 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é