Não consigo percorrer corretamente uma Lista

7 respostas
M

Pessoal,

Estou tentanto percorrer uma Lista em Java utilizando aquela forma clássica de percorrer a lista, um for tradicional. Segue o código :

package dao;
   import java.util.List; 
   import model.Usuario;

   public class TestaUsuarioDAO {

	public static void main(String[] args) {
				
		List<Usuario> lista = dao1.listaUsuarios();
		System.out.println("Tamanho da lista : " + lista.size() );
		
		for (int i = 0; i < lista.size(); i++ ) {
			
			System.out.println("-------------------------------------------------");
			System.out.println("Cpf               : " + lista.get(i).getCpf() );
			System.out.println("Nome              : " + lista.get(i).getNome() );
			System.out.println("Email Principal   : " + lista.get(i).getEmailPrincipal() );
			System.out.println("Email Alternativo : " + lista.get(i).getEmailAlternativo() );
			System.out.println("Telefone          : " + lista.get(i).getTelefone() );
			System.out.println("Perfil            : " + lista.get(i).getPerfil() );			
			
		} 		
	
	} 
		
   }

[youtube] O método acima só está listando o último usuário

CPF                    : [telefone removido]
   Nome                 : Samara Felipo
   Email Principal     : [email removido]
   Email Alternativo : [email removido]
   Telefone             : [email removido]
   Perfil                  : C

quando deveria estar trazendo o seguinte resultado

----------------------------------------------------
CPF                    : 777777777777
Nome                 : Max Carvalho
Email Principal     : [email removido]
Email Alternativo : [email removido]
Telefone             :  [telefone removido]
Perfil                  : A
-------------------------------------------------
CPF                   : [telefone removido]
Nome                 : Carlos Henrique
Email Principal    : [email removido]
Email Alternativo : [email removido]
Telefone            : [email removido]
Perfil                 : C
-------------------------------------------------
CPF                    :[telefone removido]
Nome                 : Samara Felipo
Email Principal    : [email removido]
Email Alternativo : [email removido]
Telefone             : [email removido]
Perfil                  : C
Tamanho da lista : 3

Segue, abaixo, o código que monta a lista acima

public class UsuarioDAO {

    /* atributos */
   ...
   /* metodos get e set */
   ...
   public List<Usuario> listaUsuarios() {
		
		Connection conexao = null;
		ConectaMySQL con1 = new ConectaMySQL();
		ResultSet rs;
		PreparedStatement pstmt;
		
		Usuario u2 = new Usuario();
		
		List<Usuario> listaUsuarios = new ArrayList<Usuario>();
		
		String sql_cons = "select usuario_cpf, usuario_nome, usuario_emailprinc, usuario_emailalter, " +
				          "usuario_telefone, usuario_perfil from tb_usuario ";
		
		conexao = con1.obtemConexao();
		
		try {
			
			pstmt = conexao.prepareStatement(sql_cons);
			rs = pstmt.executeQuery();
			
			while (rs.next() ) {
				
				u2.setCpf(rs.getString(1));
				u2.setNome(rs.getString(2));
				u2.setEmailPrincipal(rs.getString(3));
				u2.setEmailAlternativo(rs.getString(4));
				u2.setTelefone(rs.getString(5));
				u2.setPerfil(rs.getString(6));
				
				listaUsuarios.add(u2);
				
				System.out.println("-------------------------------------------------");
				System.out.println("CPF               : " + u2.getCpf() );
				System.out.println("Nome              : " + u2.getNome() );
				System.out.println("Email Principal   : " + u2.getEmailPrincipal() );
				System.out.println("Email Alternativo : " + u2.getEmailPrincipal() );
				System.out.println("Telefone          : " + u2.getEmailAlternativo() );
				System.out.println("Perfil            : " + u2.getPerfil() ); 
				
			}
			
		} catch (SQLException e) {
			
			e.printStackTrace();	
		
		} finally {
			
			con1.fechaConexao();
			
		}  	
		
		return listaUsuarios;
		
	}

Ao excecutar o método acima, percebe-se através dos “println” que a lista é montada corretamente.
Porém, quando o método chamador(da classe TestaUsuarioDAO) tenta percorrer a lista, só exige o último elemento.
Gostaria de resolver esse meu problema acima sem usar “Iterator” e nem “enhanced-for”.
Agradece,

Max Carvalho

7 Respostas

maschiojv

Você precisa criar um objeto Usuário para cada linha retornada do teu select, mas você está criando usuários (new Usuario()) uma vez só.

coloque o trexo Usuario u2 = new Usuario(); logo depois de while (rs.next() ) {

ViniGodoy

Outra coisa, faltou fechar o statement e o resultset no finally.
Em especial o Statement. Caso contrário, você poderá ter crash na sua aplicação.

pablouu

da forma que vc está fazendo você fica com um array de referências para o mesmo objeto, o que o maschiojv disse resolve o seu problema :wink:

M

machiojv e demais colegas do fórum,

Efetuei as modificações sugeridas e deu certo, consegui que o método Listar() de UsuarioDAO me retornasse uma lista com todos os usuarios persistidos no banco.
Essa lista está sendo repassada para um outro objeto da camada de negócios(que a está recebendo corretamente) e daí para frente é comigo.
Obrigado a todos pela valiosa ajuda até agora.
Agora, quanto ao fechamento do ResultSet e do PreparedStatement na cláusula “finally”, mas aparecem as seguintes mensagens de erro :

  • Unhandled exception type SQLException
  • The local variable rs may not have been

E, através do Quick Fix, me foram dadas as seguintes sugestões para correção :

1ª sugestão : Add throws “SQL Excpetion” declaration,

Em outras palavras, lançar esta exceção para ser tratada pelos níveis superiores da arquitetura, mas esta idéia não me agrada. Posso até estar errado, mas não gosto de “delegar muitos pepinos para serem resolvidos por objetos de níveis médio a altos da arquitetura, principalmente em se tratando de situações associadas à persistência.”

2ª sugestão : Initialize variable,

Em outras palavras, inicializar a varíavel com algum valor. Ela está sem valor, pq a execução já saiu do bloco try-catch e entrou no finally.
Pensei em inicializá-la com um valor adequado a este ponto do fluxo de execução da aplicação, mas fiquei sem saber qual seria um valor consistente para a mesma neste ponto ???

3ª sugestão : Surrond with try-catch

Como já existe um bloco try-catch, não me parece uma boa idéia realizar aninhamentos de try-catch, o código perderá a legibilidade e isto dificultará um pouco mais futuras manutenções.

Uma idéia minha

Desalocar os recursos do PreparedStatement e do ResultSet logo apó o while, ainda dentro do bloco “try”, mas ainda penso que este não seja o local mais adequado.
Fiz este teste aqui e funcionou, mas queria encontrar uma forma de fechar os dois recursos supracitados dentro do “finally”.

Alguém poderia me orientar se devo utilizar alguma das soluções de correção acima, propostas pelo Quick Fix da IDE, ou vocês teriam alguma uma outra idéia que totalmente diferente das três supracitadas ?

Agradeço-lhes mais uma vez pela atenção e paciência,

Max Carvalho

pablouu

o meu finally fica assim:

} finally {
            try {
                if (rs != null) {
                    rs.close();
                }
                if (pst != null) {
                    pst.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

pra vc chamar o rs.close e o pst.close, eles tbm lançam excessao, entao tbm devem estar em um try/catch.

espero ter ajudado. abrajos :wink:

maschiojv

pablouu:
o meu finally fica assim:

} finally {
            try {
                if (rs != null) {
                    rs.close();
                }
                if (pst != null) {
                    pst.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

pra vc chamar o rs.close e o pst.close, eles tbm lançam excessao, entao tbm devem estar em um try/catch.

espero ter ajudado. abrajos ;)

concordo, mas você também teria que inicializar as variáveis com valor null

ResultSet rs = null; PreparedStatement pstmt = null;

quanto a perca de legibilidade, eu nem acho que é tanto assim, e nem vá prejudicar futuras manutenções por tão pouco.
Você poderia extrair esse trexo do finally para um outro método:

} finally {
	close(rs, pstmt);
}

...

protected void close(ResultSet rs, PreparedStatement pstmt) {

	try {
		if (rs != null) {
			rs.close();
		}
		if (pst != null) {
			pst.close();
		}
	}
	catch (SQLException e) {
		e.printStackTrace();
	}
}

Outra saída seria fazer com que esse seu objeto ConectaMySQL criasse o Statment, o ResultSet e depois fechasse os dois, assim como a conexão, mas isso não é o ideal porque ficar abrindo e fechando conexão a cada chamada ao banco fai deixar a tua aplicação muito lenta.

E por fim, a minha solução favorita: usar o Hibernate :smiley:

K

percorra a lista com um “foreach”

for(Usuario usuario : lista){
//desse jeito ele irá percorrer a lista elemento por elemento
}
Criado 21 de outubro de 2009
Ultima resposta 23 de out. de 2009
Respostas 7
Participantes 5