Como outros já declararam, seu código está basicamente correto, embora o externo try
seja 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 DriverManager
no 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.PGSimpleDataSource
por 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 DataSource
implementação não precisa ser fechada, porque nunca é "aberta". A DataSource
nã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 DataSource
sã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 DataSource
objeto 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 try
define dois recursos: Connection
e PreparedStatement
. O interno try
define o ResultSet
recurso. 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 ResultSet
recurso será fechado automaticamente (se existir, não será nulo). Depois disso, o PreparedStatement
será 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 try
chamadas 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, ResultSet
ele 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
, PreparedStatement
e ResultSet
també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 ResultSet
como AutoCloseable
e 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