Problemas com JSF ao listar todos os registros com DataTable

Olá pessoal, estou começando agora a estudar JSF, vi alguns vídeos no Youtube e agora com o que deu para aprender estou tentando criar uma aplicação de teste apenas para ver se consigo com o JSF fazer algumas interações básicas com o MySQL.

Consigo cadastrar e alterar. Tentei localizar, mas não sei como trazer o resultado para a página xhtml, então pulei para listar todos os registros da minha tabela, onde nesta há 3 registros, sendo que somente retorna no meu xhtml o terceiro registro repetido 3 vezes e não entendo o porque disso, já fiz o método várias vezes, inclusive copiei um método que está funcionando em uma aplicação JSP e apenas fiz algumas alterações para esse pequeno teste JSF, e nada também, sempre o mesmo problema.

Resolvi colocar um System.out.prinln() para ver o que meu resultado estava retornando e para minha surpresa ele retornou meus registros repetindo eles 3 vezes. Segue a cópia da resposta no Console do Eclipse:

ID: 1 - Campo: Anderson
ID: 2 - Campo: Janaina
ID: 3 - Campo: Ola
ID: 1 - Campo: Anderson
ID: 2 - Campo: Janaina
ID: 3 - Campo: Ola
ID: 1 - Campo: Anderson
ID: 2 - Campo: Janaina
ID: 3 - Campo: Ola

Realmente não entendi.

Vou postar meu método para listar os registros:

public List<Tabela> getTabelas() {
		
		Conecta conecta = new Conecta();
		Connection conexao = conecta.abreConexao();
		List<Tabela> lista = new ArrayList<Tabela>();
		Statement consulta = null;
		ResultSet resultado = null;
		//Tabela tabela = null;
		
		String sql = "SELECT * FROM tabela";
		
		try {
			
			consulta = conexao.createStatement();
			resultado = consulta.executeQuery(sql);
			
			while (resultado.next()) {
				//tabela = new Tabela();
				
				tabela.setId(resultado.getInt("id"));
				tabela.setCampo(resultado.getString("campo"));
				
				System.out.println("ID: " + resultado.getInt("id") + " - Campo: " + resultado.getString("campo"));
				
				lista.add(tabela);
			}
			
		} catch (SQLException e) {
			context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR,
					"Erro ao localizar registro. Mensagem: " + e.getMessage(), ""));
		} finally {
			try {
				consulta.close();
				resultado.close();
				conexao.close();
			} catch (Throwable e) {
				context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR,
						"Erro ao fechar operação de Localização. Mensagem: " + e.getMessage(), ""));
			}
		}
		
		return lista;
		
	} //fim listar

Agora vou postar minha página xhtml onde mostra o terceiro registro repetindo 3 vezes:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:ui="http://java.sun.com/jsf/facelets"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:f="http://java.sun.com/jsf/core">

	<h:dataTable value="#{tabelaBean.tabelas2}" var="tab" border="1">
		<h:column>
			<h:outputText value="#{tab.id}"/>
		</h:column>
		
		<h:column>
			<h:outputText value="#{tab.campo}"/>
		</h:column>
	</h:dataTable>
	
	<h:messages/>
	
	<h:outputLink value="index.jsf"><h:outputText value="Voltar"/></h:outputLink>

</html>

Por favor, alguém poderia me ajudar?

Fiquei o dia todo tentando arrumar isso sem sucesso.

Desde já fico grato.

cara,

posta sua classe referente ao tabelaBean.

t+

[quote=alissonvla]cara,

posta sua classe referente ao tabelaBean.

t+[/quote]

Opa, estou postando agora mesmo a classe TabelaBean completa:

package bean;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.context.FacesContext;

import modelo.Tabela;
import conexao.Conecta;

@ManagedBean(name = "tabelaBean")
@RequestScoped
public class TabelaBean {

	Tabela tabela = new Tabela();
	
	FacesContext context = FacesContext.getCurrentInstance();

	public String salvar() {
		
		Conecta conecta = new Conecta();
		Connection conexao = conecta.abreConexao();
		PreparedStatement pstmInsere = null;
		
		String sql = "INSERT INTO tabela (campo) VALUES (?)";
		
		try {
			
			pstmInsere = conexao.prepareStatement(sql);
			
			pstmInsere.setString(1, tabela.getCampo());
			
			pstmInsere.executeUpdate();
			
			context.addMessage(null, new FacesMessage("O registro foi adicionado com sucesso", ""));
			
		} catch (SQLException e) {
			context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR,
					"Erro ao inserir registro. Mensagem: " + e.getMessage(), ""));
		} finally {
			try {
				pstmInsere.close();
				conexao.close();
			} catch (Throwable e) {
				context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR,
						"Erro ao fechar operação de inserção. Mensagem: " + e.getMessage(), ""));
			}
		}
		
		return "resposta";
		
	} //fim salvar
	
	public String atualizar() {
		
		Conecta conecta = new Conecta();
		Connection conexao = conecta.abreConexao();
		PreparedStatement pstmAtualiza = null;
		
		String sql = "UPDATE tabela SET campo=? WHERE id=?";
		
		try {
			
			pstmAtualiza = conexao.prepareStatement(sql);
			
			pstmAtualiza.setString(1, tabela.getCampo());
			pstmAtualiza.setInt(2, tabela.getId());
			
			pstmAtualiza.executeUpdate();
			
			context.addMessage(null, new FacesMessage("O registro foi atualizado com sucesso", ""));
			
		} catch (SQLException e) {
			context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR,
					"Erro ao atualizar registro. Mensagem: " + e.getMessage(), ""));
		} finally {
			try {
				pstmAtualiza.close();
				conexao.close();
			} catch (Throwable e) {
				context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR,
						"Erro ao fechar operação de Atualização. Mensagem: " + e.getMessage(), ""));
			}
		}
		
		return "resposta";
		
	} // fim atualiza
	
	public String lacalizar() {
		
		Conecta conecta = new Conecta();
		Connection conexao = conecta.abreConexao();
		PreparedStatement pstmLocaliza = null;
		ResultSet resultado = null;
		//Tabela tabela = null;
		
		String sql = "SELECT * FROM tabela WHERE id=?";
		
		try {
			
			pstmLocaliza = conexao.prepareStatement(sql);
			
			pstmLocaliza.setInt(1, tabela.getId());
			
			resultado = pstmLocaliza.executeQuery();
			
			if (resultado.next()) {
				tabela.setId(new Integer(resultado.getInt("id")));
				tabela.setCampo(resultado.getString("campo"));
			}
			
			
		} catch (SQLException e) {
			context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR,
					"Erro ao localizar registro. Mensagem: " + e.getMessage(), ""));
		} finally {
			try {
				pstmLocaliza.close();
				resultado.close();
				conexao.close();
			} catch (Throwable e) {
				context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR,
						"Erro ao fechar operação de Localização. Mensagem: " + e.getMessage(), ""));
			}
		}
		
		return "localizarResultado";
		
	}//fim localiza
		
	public List<Tabela> getTabelas() {
		
		Conecta conecta = new Conecta();
		Connection conexao = conecta.abreConexao();
		List<Tabela> lista = new ArrayList<Tabela>();
		Statement consulta = null;
		ResultSet resultado = null;
		
		String sql = "SELECT * FROM tabela";
		
		try {
			
			consulta = conexao.createStatement();
			resultado = consulta.executeQuery(sql);
			
			while (resultado.next()) {
				
				tabela.setId(resultado.getInt("id"));
				tabela.setCampo(resultado.getString("campo"));
				
				System.out.println("ID: " + resultado.getInt("id") + " - Campo: " + resultado.getString("campo"));
				
				lista.add(tabela);
			}
			
		} catch (SQLException e) {
			context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR,
					"Erro ao localizar registro. Mensagem: " + e.getMessage(), ""));
		} finally {
			try {
				consulta.close();
				resultado.close();
				conexao.close();
			} catch (Throwable e) {
				context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR,
						"Erro ao fechar operação de Localização. Mensagem: " + e.getMessage(), ""));
			}
		}
		
		return lista;
		
	} //fim listar
	
	public void apagar() {
		
		Conecta conecta = new Conecta();
		Connection conexao = conecta.abreConexao();
		PreparedStatement pstmApagar = null;
		//TabelaBean tabela = null;
		
		String sql = "DELETE FROM tabela WHERE id=?";
		
		try {
			
			pstmApagar = conexao.prepareStatement(sql);
			
			pstmApagar.setInt(1, tabela.getId() );
			
			pstmApagar.executeUpdate();
			
		} catch (SQLException e) {
			context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR,
					"Erro ao apagar registro. Mensagem: " + e.getMessage(), ""));
		} finally {
			try {
				pstmApagar.close();
				conexao.close();
			} catch (Throwable e) {
				context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR,
						"Erro ao fechar operação de Exclusão. Mensagem: " + e.getMessage(), ""));
			}
		}
		
	}
	
	//get & set
	public Tabela getTabela() {
		return tabela;
	}

	public void setTabela(Tabela tabela) {
		this.tabela = tabela;
	}
	
}

Vou aproveitar e colocar a classe conecta também só por desencargo de consciência:

package conexao;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
//import javax.faces.bean.ManagedBean;
//import javax.faces.bean.RequestScoped;

//@ManagedBean(name="conecta")
//@RequestScoped
public class Conecta {
	
	Connection conexao = null;
	FacesContext context = FacesContext.getCurrentInstance();
	
	public Connection abreConexao() {
		
		try {
			
			Class.forName("com.mysql.jdbc.Driver");
			
			String url = "jdbc:mysql://localhost:3306/jsfbanco";
			String usuario = "teste";
			String senha = "teste";
			conexao = DriverManager.getConnection(url, usuario, senha);
		
			//context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR,
				//	"Conexão efetuada com sucesso!", ""));
			
		} catch (ClassNotFoundException e) {
			context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR,
					"Classe não encontrada. Mensagem: " + e.getMessage(), ""));
		} catch (SQLException e) {
			context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR,
					"Erro de conexão com o banco de dados. Mensagem: " + e.getMessage(), ""));
		}
			
		return conexao;
	}
	
}

Pronto, está aí a classe TabelaBean e a classe Conecta também.

Uma observação, os métodos de localizar e apagar eu ainda não usei, quer dizer, o localizar eu tentei, mas não sei como retornar o registro no xhtml, o apagar eu apenas fiz o método mas não usei, proém deve funcionar normal este.

cara,

vc tem que fazer assim

public List<Tabela> getTabelas() {  
          
        Conecta conecta = new Conecta();  
        Connection conexao = conecta.abreConexao();  
        List<Tabela> lista = new ArrayList<Tabela>();  
        Statement consulta = null;  
        ResultSet resultado = null;  
          
        String sql = "SELECT * FROM tabela";  
          
        try {  
              
            consulta = conexao.createStatement();  
            resultado = consulta.executeQuery(sql);  
              
            while (resultado.next()) {  
                Tabela tabela = new Tabela();
                tabela.setId(resultado.getInt("id"));  
                tabela.setCampo(resultado.getString("campo"));  
                  
                System.out.println("ID: " + resultado.getInt("id") + " - Campo: " + resultado.getString("campo"));  
                  
                lista.add(tabela);  
            }  
              
        } catch (SQLException e) {  
            context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR,  
                    "Erro ao localizar registro. Mensagem: " + e.getMessage(), ""));  
        } finally {  
            try {  
                consulta.close();  
                resultado.close();  
                conexao.close();  
            } catch (Throwable e) {  
                context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR,  
                        "Erro ao fechar operação de Localização. Mensagem: " + e.getMessage(), ""));  
            }  
        }  
          
        return lista;  
          
    } //fim listar  
     

t+

1 curtida

Valeu mesmo cara, muito obrigado mesmo, fico te devendo.

Eu até pensei em por alí um objeto Tabela, mas em uma vídeo aula que vi no Youtube o cara tinha dito que eu declarava fora do método e usaria ela em todos os métodos sem precisar declarar. Apesar que essa vídeo aula não tinha exemplos rodando com o banco, somente algumas explicações. Em todo caso, não pensei que o cara poderia está errado e com isso assim que criei o método getTabelas() eu omiti essa declaração seguindo a orientação do cara. É bom que assim eu aprendo a não confiar 100% nesses vídeos.

Meu velho, aproveitando a oportunidade, você poderia me dizer como faço para retornar na página xhtml o meu registro localizado no meu método Localizar?

Eu não tenho ideia de como trazer ele para a página. Até dois dias atrás eu só usava JSP com servlet rsss.

Em todo caso, muito obrigado mais uma vez, sua ajuda foi fundamental para eu não dormir estressado hoje com isso rss.

[Editado]
Obs.: No console do Eclipse os registros ainda são mostrados repetindo 3 vezes como comentei antes, estranho. Mas em todo caso na minha aplicação, digo, no xhtml me retorna corretamente.

vc quer selecionar um registro no seu datatable e monstrar na outra pagina?

t+

[quote=alissonvla]vc quer selecionar um registro no seu datatable e monstrar na outra pagina?

t+[/quote]

Na verdade eu queria fazer uma tela de pesquisa, com um local para digitar o código do campo, se o campo fosse encontrado então ia me retornar o usuário em outra página, porém do jeito que você comentou acho que é a mesma coisa, só que da maneira que você disse acredito não ser preciso digitar o código.

Eu quero aprender isso para depois poder usar os resultados da maneira que eu quiser. Por exemplo, fora do DataTable, em uma frase por exemplo eu obter o valor do campo e fazer uma frase de boas vindas: Olá CAMPO, seja bem vindo. Tipo isso.

O JSF é bem diferente, apesar de realmente o JSP deixar o código bem bagunçado, era fácil eu obter uma informação do banco e usar ela no conteúdo do meu site, com JSF estou realmente perdido rss.

Voltando ao assunto, acho que da maneira que você falou já está de bom tamanho, não quero te incomodar muito. Se puder me ajudar nisso, o resto eu vou pesquisar depois, ainda não achando nada retorno do fórum e abuso quem tiver disponível rsss.

cara,

vc vai ter que fazer algo assim.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"   
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
  
<html xmlns="http://www.w3.org/1999/xhtml"  
    xmlns:ui="http://java.sun.com/jsf/facelets"  
    xmlns:h="http://java.sun.com/jsf/html"  
    xmlns:f="http://java.sun.com/jsf/core">  
  
    <h:dataTable value="#{tabelaBean.tabelas2}" var="tab" border="1">  
        <h:column>  
            <h:outputText value="#{tab.id}"/>  
        </h:column>  
          
        <h:column>  
            <h:outputText value="#{tab.campo}"/>  
        </h:column>  
		<h:column style="width:32px">  
			<h:commandButton action="#{tabelaBean.editarTabela}" immediate="true" value="Editar">
				<f:setPropertyActionListener value="#{tab}" target="#{tabelaBean.tabelaSelecionada}"/>  
			</h:commandButton>
		</h:column>
    </h:dataTable>  
      
    <h:messages/>  
      
    <h:outputLink value="index.jsf"><h:outputText value="Voltar"/></h:outputLink>  
  
</html>

@ManagedBean(name = "tabelaBean")  
@RequestScoped  
public class TabelaBean { 

	private Tabela tabelaSelecionada;
	
	public String editarTabela(){
		return "localizarResultado";
	}
	
	public Tabela getTabelaSelecionada(){
		return this.tabelaSelecionada;
	}
	
	public void setTabelaSelecionada(Tabela tabelaSelecionada){
		this.tabelaSelecionada = tabelaSelecionada;
	}

}

t+

Opa, bom dia amigo!

Mais uma vez obrigado pela ajuda.

Então, fiz como você falou, na lista aparece os botões de editar para cada registro, porém nenhum deles tem ação ao clicar. Porque será?