Como han dicho otros, su código es básicamente correcto, aunque el exterior no tryes necesario. Aquí hay algunos pensamientos más.
DataSource
Otras respuestas aquí son correctas y buenas, como la respuesta aceptada por bpgergo. Pero ninguno de ellos muestra el uso DataSource, comúnmente recomendado sobre el uso de DriverManageren Java moderno.
Entonces, en aras de la integridad, aquí hay un ejemplo completo que obtiene la fecha actual del servidor de la base de datos. La base de datos utilizada aquí es Postgres . Cualquier otra base de datos funcionaría de manera similar. Reemplazaría el uso de org.postgresql.ds.PGSimpleDataSourcecon una implementación DataSourceapropiada para su base de datos. Es probable que su controlador particular o grupo de conexiones proporcione una implementación si sigue esa ruta.
Una DataSourceimplementación no necesita cerrarse, porque nunca se "abre". A DataSourceno es un recurso, no está conectado a la base de datos, por lo que no contiene conexiones de red ni recursos en el servidor de la base de datos. A DataSourcees simplemente información necesaria cuando se realiza una conexión a la base de datos, con el nombre o la dirección de red del servidor de la base de datos, el nombre de usuario, la contraseña de usuario y varias opciones que desea especificar cuando finalmente se realiza una conexión. Por lo tanto, su DataSourceobjeto de implementación no va dentro de sus paréntesis de prueba con recursos.
Prueba anidada con recursos
Su código hace un uso adecuado de las declaraciones anidadas de prueba con recursos.
Observe en el código de ejemplo a continuación que también usamos la sintaxis try-with-resources dos veces , una anidada dentro de la otra. El exterior trydefine dos recursos: Connectiony PreparedStatement. Lo interno trydefine el ResultSetrecurso. Esta es una estructura de código común.
Si se lanza una excepción desde el interior y no se captura allí, el ResultSetrecurso se cerrará automáticamente (si existe, no es nulo). A continuación, PreparedStatementse cerrará y, por último, Connectionse cerrará. Los recursos se cierran automáticamente en orden inverso en el que se declararon dentro de las declaraciones de prueba con recursos.
El código de ejemplo aquí es demasiado simplista. Tal como está escrito, podría ejecutarse con una única declaración de prueba con recursos. Pero en un trabajo real, es probable que esté haciendo más trabajo entre el par de tryllamadas anidadas . Por ejemplo, puede estar extrayendo valores de su interfaz de usuario o un POJO, y luego pasarlos para cumplir con los ?marcadores de posición dentro de su SQL a través de llamadas a PreparedStatement::set…métodos.
Notas de sintaxis
Punto y coma final
Observe que el punto y coma que sigue a la última declaración de recursos entre paréntesis de try-with-resources es opcional. Lo incluyo en mi propio trabajo por dos razones: consistencia y parece completo, y hace que copiar y pegar una mezcla de líneas sea más fácil sin tener que preocuparme por los puntos y comas al final de la línea. Su IDE puede marcar el último punto y coma como superfluo, pero no hay nada de malo en dejarlo.
Java 9: utilice vars existentes en try-with-resources
Nuevo en Java 9 es una mejora de la sintaxis de prueba con recursos. Ahora podemos declarar y completar los recursos fuera de los paréntesis de la trydeclaración. Todavía no he encontrado esto útil para los recursos de JDBC, pero tenlo en cuenta en tu propio trabajo.
ResultSet debería cerrarse, pero puede que no
En un mundo ideal, ResultSetse cerraría como promete la documentación:
Un objeto ResultSet se cierra automáticamente cuando el objeto Sentencia que lo generó se cierra, se vuelve a ejecutar o se usa para recuperar el siguiente resultado de una secuencia de resultados múltiples.
Desafortunadamente, en el pasado, algunos controladores de JDBC no pudieron cumplir esta promesa. Como resultado, muchos programadores JDBC aprendieron a cierre de forma explícita todos sus recursos JDBC entre ellos Connection, PreparedStatementy ResultSettambién. La sintaxis moderna de prueba con recursos ha hecho que sea más fácil y con un código más compacto. Tenga en cuenta que el equipo de Java se tomó la molestia de marcar ResultSetcomo AutoCloseable, y sugiero que hagamos uso de eso. El uso de una prueba con recursos alrededor de todos sus recursos JDBC hace que su código se documente más en cuanto a sus intenciones.
Ejemplo de código
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()) {porque el objeto de declaración que lo generó cierra automáticamente un objeto ResultSet