ResultSet fechando "sozinho"

Fala galera,

Tenho uma duvida com relação ao funcionamento do ResultSet.

Tenho uma classe DAO que tem um metodo getListaCliente que abre um RS e no meio do metodo faço uma chamada para getListaContato, que é parecido com getListaCliente. Cada metodo abre seu RS, mas quando o metodo devolve o valor e começa o loop novamente dentro de getListaCliente, ele volta com RS fechado.

Será que deu pra entender?

public List<Cliente> getListaCliente(){
		List <Cliente> clientes = new ArrayList<Cliente>();
		String sql = "select * from cliente where ativo = 1";
		
		Cliente c;
		
		try {
			stm = conn.prepareStatement(sql);
			rs = stm.executeQuery();
			
			while (rs.next()){ //na primeira ele funciona, mas quando ele volta do getListaContato, volta fechado
				c = new Cliente();
				...
				c.setContatoList(getListaContato(rs.getInt("codiclie"))); // getListaContato tem o codigo parecido com este
				clientes.add(c);
				
			}
			rs.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			JOptionPane.showMessageDialog(null, "Não foi possível selecionar os clientes.", "Atenção!!!", JOptionPane.ERROR_MESSAGE);
		} 
		
		return clientes;
	}

Alguem ja passou por isto?

O outro método fecha a conexão?

Não fecha nao. Eu ate fechava, dai como deu erro entao nao fechei mais, mas continua com o mesmo problema. Aproveitando, se tenho duas instancias de RS, fecho uma, a outra fecha tbm? Lembrando que cada RS esta em um metodo.

Não deveria fechar, nem em métodos diferentes, nem no mesmo método.
Só existe problema se ambos os Resultsets compartilharem o mesmo Statement.

Pode postar o código do outro método?

segue codigo:

[code]
public List getListaContato(int id) {
List contatoList = new ArrayList();
String sql = "SELECT * FROM CONTATOCLIENTE WHERE codiClie = " + id;
try {
PreparedStatement stm = conn.prepareStatement(sql);
ResultSet rs = stm.executeQuery();

		while (rs.next()){
			Contato contato = new Contato();
			contato.setNome(rs.getNString("nome"));
			contato.setTelefone(rs.getNString("telefone"));
			contatoList.add(contato);
		}

// rs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return contatoList;
}[/code]

Entao, nao vi nada de estranho neste codigo, veja c vc pode me ajudar por favor…

vlw

Acho que ja me liguei o que eh… eu estou compartilhando o mesmo ConnectFactory que fiz… dai eu acabei de criar um outro conn dentro do metodo e rolou… sera que isto procede, para cada stm tenho q ter um conn novo?

Só se for uma particularidade do banco que você estiver usando. Normalmente, um conn suporta vários statements. Cada um com um resultset.

Só um detalhe. É uma boa prática você:

  1. Utilizar um pool de conexões (como c3p0 ou jakarta.dbcp);
  2. Fechar resultsets, stataments e conexões no bloco finally (no caso das conexões, elas apenas irão retornar para o pool);

Isso evita não só problemas como o que você está tendo, mas também problemas ao executar coisas em threads separadas.

E para listas, como a que você está carregando, pode ser uma boa fazer através de lazy-loading. Deixe a lista como nula e, na primeira chamada ao getter da lista, carregue-a do banco. Isso evita carregar diversas listas quando vc for mostrar um JTable de contatos, por exemplo, sendo que seu usuário irá abrir apenas um ou dois contatos.

Cara pra esse seu caso pq vc não usa o Statement apenas. O PreparedStatement serve pra esse caso tbm, mas ele foi criado mais para parametrizar a consulta. E o Statement dá mensos problemas e é mais rápido :shock:

É uma boa prática não utilizar o Statement. A diferença de performance é irrisória, e você não ganha nada com isso. Sem falar que você corre o risco de um programador um pouco menos experiente começar a concatenar strings com +

O banco que estou usando é o firebird. Estou aprendendo a trabalhar com ele. Acredito que ele nao eh limitado como voce sugere no caso do problema com o conn neh?

Não sei, não conheço esse banco. =/