E se eu não fechar um ResultSet?

Boa tarde…

Estou com uma duvida com relação a ResultSet e GC.

Caso eu abra um ResultSet SOMENTE LEITURA (ou seja não adianta nada o CLOSE_CURSOR_AT_COMMIT) dentro de um método qualquer e dentro deste método eu percorra todo ele e coloque os valores em uma JTable só isso. Porém ao encerrar o método eu esqueça de executar o close() do ResultSet, o que acontece com a memória da máquina os registros do ResultSet ficam retidos ou o GC consegue elimina-los ja que não existe mais nenhuma referencia para o Objeto ResultSet.

Muito obrigado pela atenção…

Olá

Provavelmente vai ficar vagando pela memória até o fim do método depois do que todas as suas variáveis locais vão para a “zona de rebaixamento” ou para o espaço.

[]s
Luca

Assim que você fechar a conexão ou o statement que geraram esse result set (ou mandar o mesmo statement executar outro comando) esse resultset é fechado.

O problema é não fechar o statement ou a conexão, aí sim você vai juntar objetos e recursos desnecessariamente.

Obrigado pela ajuda, mas deixa eu pedir um conselho…

É o seguinte aqui no meu trabalho não usamos nenhuma ORM, então fazemos tudo na mão, usamos Daos e tal mas tudo com JDBC.

Bom quando a consulta retorna Vo´s completos, tipo Select * from Cliente tudo bem eu abro um ResultSet faço um for por ele Populo uma lista de Vo´s fecho o ResultSet retorno a lista e ta tudo beleza.

Porém existem algumas consultas que não da pra retornar Vo porque ta pegando um pouquinho de campo de varias tabelas com Joins, etc, Ai mora o problema tive pensando em Popula List<Object[]> como o hibernate faz então eu posso fechar o resultSet antes de retornar o List mas isso demora mais pra ser feito do que retornar direto o ResultSet mas com RS quem ta desenvolvendo precisa lembrar de fechar sem falar que fica muito menos genérico do que o List…

E ai qual o melhor e como vcs fazem isso (se é que existe mais alguem que não usa Hibernate hj em dia :lol: )

Retorne um List de object mesmo ou então dê uma olhada em RowSets -> http://java.sun.com/developer/Books/JDBCTutorial/chapter5.html

Veja principalmente o CachedRowSet, que é um rowset desconectado e que não vai lhe dar dor de cabeça se o cara esquecer de “fechar”.

Olá

Se você usa JDBC, deve saber que as novas versões do JDBC oferecem coisas muito interessantes. Inclusive o JDBC 4.0 que vem com o Java 6 ficou um pouquinho mais fácil de usar.

Há muito material na Internet sobre facilidades do JDBC &gt= 2.0 mas nosso amigo Daniel Quirino aqui do GUJ escreveu um texto ótimo e rápido que pode lhe interessar:
Dando vida nova ao seu código JDBC

[]s
Luca

Olá

Isso, era exatamente o artigo do Daniel sobre CachedRowSet que eu fui buscar.

[]s
Luca

Pô, o Delphi tem um lance desse desde a versão 7, conhecido como ClientDataSet. Eita Java…

Olá

O JDBC 2.0 que trouxe isto como novidade foi lançado em 2000 e o Delphi 7 é do fim de 2002.

[]s
Luca

Valeu pela força galera dei uma olhada e testei esse CachedRowSet mas olhem o resultado

Teste: selecionar todos os registros de uma tabela com 14 colunas e 1350 registros e imprimir quantos registros foram selecionador (1350 lógico mas é só teste):

ResultSet:

	    	long t1 = System.currentTimeMillis();
	    	ResultSet rs = cnn.prepareStatement("Select * from Aa13", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY).executeQuery();
	    	rs.last();
	    	System.out.println(rs.getRow());
                                rs.close();
	    	System.out.println( System.currentTimeMillis()-t1);

RESULTADO EM 78 milis

List<Object[]>

	    	long t1 = System.currentTimeMillis();
	    	ResultSet rs = cnn.prepareStatement("Select * from Aa13").executeQuery();
	    	List<Object[]> objects = new ArrayList<Object[]>();
	    	while(rs.next()){
	    		int qtdColuna = rs.getMetaData().getColumnCount();
	    		Object[] reg = new Object[qtdColuna];
	    		for(int col = 0; col < qtdColuna; col++){
					reg[col] = rs.getObject(col+1);
				}
	    		objects.add(reg);
	    	}
                                rs.close();
	    	System.out.println(objects.size());
	    	System.out.println( System.currentTimeMillis()-t1);


RESULTADO EM 219 milis

CachedRowSet

	    	long t1 = System.currentTimeMillis();
	    	CachedRowSet cache = new CachedRowSetImpl();
	    	cache.setCommand("Select * from Aa13");
	    	cache.setType(ResultSet.TYPE_SCROLL_INSENSITIVE);
	    	cache.setConcurrency(ResultSet.CONCUR_READ_ONLY);
	    	cache.execute(cnn);
	    	cache.last();
	    	System.out.println(cache.getRow());
	    	System.out.println( System.currentTimeMillis()-t1);

RESULTADO EM 375 milis  :shock: 

Ou seja é claro que o CachedRowSet me da facilidade de fazer update e etc mas acho que vou ficar com a Lista de Object[] mesmo.

Muito obrigado pela ajuda…

[quote=Luca]Olá

O JDBC 2.0 que trouxe isto como novidade foi lançado em 2000 e o Delphi 7 é do fim de 2002.

[]s
Luca[/quote]

Vixi, que legal! Pelo menos essa! :smiley: Então retificando:

Pô, o Delphi tem um lance desse desde a versão 7, conhecido como ClientDataSet. Copiado do Java :smiley:

Revivendo o tópico… fiquei com a seguinte dúvida…
Se eu fechar a Conexão, eu não preciso me preocupar em fechar o ResultSet, Statement e o PreparedStatement?
Pode acontecer algum, se por acaso eu vier à abrir uma conexão, trazer uns dados e fechar a conexão em seguida…
depois, abrir outra conexão e trazer outros dados e fechar novamente a conexão recém aberta?