Como han dicho otros, su código es básicamente correcto, aunque el exterior no try
es 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 DriverManager
en 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.PGSimpleDataSource
con una implementación DataSource
apropiada para su base de datos. Es probable que su controlador particular o grupo de conexiones proporcione una implementación si sigue esa ruta.
Una DataSource
implementación no necesita cerrarse, porque nunca se "abre". A DataSource
no 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 DataSource
es 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 DataSource
objeto 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 try
define dos recursos: Connection
y PreparedStatement
. Lo interno try
define el ResultSet
recurso. Esta es una estructura de código común.
Si se lanza una excepción desde el interior y no se captura allí, el ResultSet
recurso se cerrará automáticamente (si existe, no es nulo). A continuación, PreparedStatement
se cerrará y, por último, Connection
se 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 try
llamadas 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 try
declaració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, ResultSet
se 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
, PreparedStatement
y ResultSet
tambié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 ResultSet
como 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