JDBC: Fechar Connection antes de pegar resultados. Pode?

6 respostas
Rafael_Afonso

Olá:

Segue o código:

public class Teste {

	public static void main(String[] args) throws Exception {
		Class.forName("org.postgresql.Driver");
		Statement stmt = null;
		Connection conn = null;
		ResultSet rs = null;
		try {
			try {
				conn = DriverManager.getConnection("jdbc:postgresql:base", "Rafael U. C. Afonso", "");
				stmt = conn.createStatement();
				rs = stmt.executeQuery("SELECT * FROM cliente");
			} finally {
				conn.close();
			}
			while(rs.next()) {
				System.out.println(rs.getInt(1) + "-" + rs.getString(2));
			}
		} finally {
			stmt.close();
			rs.close();
		}
	}
}

Como podem ver, estou fechando a conexão antes de pegar os resultados do ResultSet. O programa roda normalmente. Se eu colocar stmt.close() dentro do primeiro finally, uma exceção é disparada.
:?: A minha dúvida é: Isto está certo? Se não, por quê? Me convençam que isto está errado.

Grato,

6 Respostas

RodrigoSol

La vai um chute:
Isso ocorre por que o ResultSet é aberto como desconectado…

J

O ResultSet é um cursor criado em memória e depois de criado, não precisa mais da conexão com o banco.

urubatan

não é não, o resultset não é um cursos em memoria, até por isto, que cada driver tem uma implementação de ResultSet
ele vai fazendo o fetch do banco a cada next (bom, isto depende de configurações, mas a ideia é esta)

wbsouza

Vc não deve fechar o connection antes do ResultSet! Como o urubatan disse, fica um cursor ativo para trazer os registros sob-demanda.

[]s, Welington B. Souza

wbsouza

Vai aí o seu código um pouco "melhorado" para se trabalhar com JDBC.

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class Teste {

	public static void main(String[] args) {
		Statement stmt = null;
		Connection conn = null;
		ResultSet rs = null;
		try {
			Class.forName("org.postgresql.Driver");
			conn = DriverManager.getConnection("jdbc:postgresql:base", 
				"Rafael U. C. Afonso", "");
			stmt = conn.createStatement();
			rs = stmt.executeQuery("SELECT * FROM cliente");
			while (rs.next()) {
				System.out.println(rs.getInt(1) + "-" + rs.getString(2));
			}
		}
		catch (ClassNotFoundException e1) {
			System.out.println("Erro ao Carregar o JDBC Driver: " + 
				e1.getMessage());
		}
		catch (SQLException e2) {
			System.out.println(e2.getMessage());
		}
		finally {
			closeResources(conn, stmt, rs);
		}
	}
	
	private static void closeResources(Connection conn, 
		Statement stmt, ResultSet rs) {
			
		if (rs != null) {
			try {
				rs.close();
			}
			catch (SQLException e) {
				System.out.println(e.getMessage());
			}
		}
		if (stmt != null) {
			try {
				stmt.close();
			}
			catch (SQLException e) {
				System.out.println(e.getMessage());
			}
		}
		if (conn != null) {
			try {
				conn.close();
			}
			catch (SQLException e) {
				System.out.println(e.getMessage());
			}
		}	
	}
}

[]s, Welington B. Souza

Rafael_Afonso

Olá:

Urubatan: De fato pensei melhor e também acho que isso deve depender da implementação de cada driver. Mesmo se estes drivers forem para o mesmo BD.
Welington: Já estou usando um método parecido com o seu no meu projeto.
Eu gostaria de ter um jeito de me livrar das classes que não vou usar mais (como o Connection e o Statement) depois de executar a query para otimizar recursos. Entretanto parece que vou ter que carregar o trio Connection-PrepaedStatement-ResultSet até o fim da minha transação. Como dizem, a otimização precoce é a raiz de todo o mal. :wink:

Grato,

Criado 29 de outubro de 2003
Ultima resposta 30 de out. de 2003
Respostas 6
Participantes 5