Como outros já declararam, seu código está basicamente correto, embora o externo tryseja desnecessário. Aqui estão mais alguns pensamentos.
DataSource
Outras respostas aqui são corretas e boas, como a resposta aceita por bpgergo. Mas nenhum dos programas mostra o uso de DataSource, comumente recomendado sobre o uso DriverManagerno Java moderno.
Portanto, por uma questão de integridade, aqui está um exemplo completo que busca a data atual do servidor de banco de dados. O banco de dados usado aqui é o Postgres . Qualquer outro banco de dados funcionaria da mesma forma. Você substituiria o uso de org.postgresql.ds.PGSimpleDataSourcepor uma implementação deDataSource apropriada ao seu banco de dados. Provavelmente, uma implementação é fornecida pelo seu driver ou pool de conexão específico, se você seguir esse caminho.
Uma DataSourceimplementação não precisa ser fechada, porque nunca é "aberta". A DataSourcenão é um recurso, não está conectado ao banco de dados e, portanto, não mantém conexões de rede nem recursos no servidor de banco de dados. A DataSourcesão simplesmente as informações necessárias ao fazer uma conexão com o banco de dados, com o nome ou endereço da rede do servidor de banco de dados, o nome do usuário, a senha do usuário e as várias opções que você deseja especificar quando uma conexão for finalmente estabelecida. Portanto, seu DataSourceobjeto de implementação não entra nos parênteses da tentativa com recursos.
Tentativa aninhada com recursos
Seu código utiliza corretamente as instruções try-with-resources aninhadas.
Observe no código de exemplo abaixo que também usamos a sintaxe try-with-resources duas vezes , uma aninhada dentro da outra. O externo trydefine dois recursos: Connectione PreparedStatement. O interno trydefine o ResultSetrecurso. Essa é uma estrutura de código comum.
Se uma exceção for lançada a partir da interna e não for capturada lá, o ResultSetrecurso será fechado automaticamente (se existir, não será nulo). Depois disso, o PreparedStatementserá fechado, e por último o Connectioné fechado. Os recursos são fechados automaticamente na ordem inversa na qual foram declarados nas instruções try-with-resource.
O código de exemplo aqui é excessivamente simplista. Conforme escrito, ele pode ser executado com uma única instrução try-with-resources. Mas, em um trabalho real, você provavelmente fará mais trabalho entre o par de trychamadas aninhadas . Por exemplo, você pode extrair valores de sua interface com o usuário ou de um POJO e passá-los para preencher ?espaços reservados em seu SQL por meio de chamadas para PreparedStatement::set…métodos.
Notas de sintaxe
Ponto e vírgula à direita
Observe que o ponto-e-vírgula após a última instrução de recurso entre parênteses da tentativa com recursos é opcional. Eu o incluo no meu próprio trabalho por duas razões: Consistência e aparência completa, e facilita a cópia e a colagem de uma mistura de linhas sem ter que se preocupar com ponto e vírgula no final da linha. Seu IDE pode sinalizar o último ponto-e-vírgula como supérfluo, mas não há mal em deixá-lo.
Java 9 - Use vars existentes em try-with-resources
O que há de novo no Java 9 é um aprimoramento da sintaxe de tentativa com recursos. Agora podemos declarar e preencher os recursos fora dos parênteses dotry declaração. Ainda não achei isso útil para os recursos JDBC, mas lembre-se de seu próprio trabalho.
ResultSet deve fechar-se, mas pode não
Em um mundo ideal, ResultSetele se fecha como a documentação promete:
Um objeto ResultSet é fechado automaticamente quando o objeto Statement que o gerou é fechado, reexecutado ou usado para recuperar o próximo resultado de uma sequência de vários resultados.
Infelizmente, no passado, alguns drivers JDBC falharam em cumprir essa promessa. Como resultado, muitos programadores JDBC aprendeu a fechar explicitamente todos os seus recursos JDBC incluindo Connection, PreparedStatemente ResultSettambém. A sintaxe moderna da tentativa com recursos tornou isso mais fácil e com código mais compacto. Observe que a equipe Java se deu ao trabalho de marcar ResultSetcomo AutoCloseablee sugiro que façamos uso disso. Usar uma tentativa com recursos em torno de todos os seus recursos JDBC torna seu código mais auto-documentado quanto às suas intenções.
Exemplo 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 Um ResultSet objeto é automaticamente fechada pelo objeto Statement que o gerou