TableView repetindo o último conteúdo da ObservableList várias vezes

Boa tarde, estou tentando fazer o conteúdo da tabela do banco de dados aparecer na minha TableView., mas o conteúdo da última linha da ObservableList se repete e somente ele aparece, várias vezes(a quantidade de itens que o método retorna é a quantidade de vezes que ele aparece). Já vi em outros fórums falando pra criar uma UserMaster, mas não achei como importar essa classe.
Mesmo sem usar o Banco o último item é repetido e só ele aparece.

O método é esse:

	public static void consultarDados() {
		ObservableList<Produto> obsProduto = FXCollections.observableArrayList();
		try {
			Class.forName("com.mysql.jdbc.Driver");

			Connection conexao = DriverManager.getConnection("jdbc:mysql://localhost:3306/marquinhos", "root", "9GSFna)<161LYgt");

			String query = "SELECT * FROM produto WHERE nome LIKE ?";

			PreparedStatement stmt = conexao.prepareStatement(query);

			stmt.setString(1, "%" + Consulta.txtBuscar.getText() + "%");

			//
			ResultSet rs = stmt.executeQuery();

			//Popular Tabela



		while(rs.next()) {
			// System.out.println("Nome -> " + rs.getString("nome"));    //rs.getString("nomeDaColunaNoBancoDeDados")
			Consulta.lblProduto.setText(Consulta.lblProduto.getText() + rs.getString("nome") + "          \n");//
			Consulta.lblDescricao.setText(Consulta.lblDescricao.getText() + rs.getString("descricao") + "          \n");//
			Consulta.lblPreco.setText(Consulta.lblPreco.getText() + rs.getString("preco") + "          \n");//
			Consulta.lblQuantidade.setText(Consulta.lblQuantidade.getText() + rs.getString("quantidade") + "          \n");//

			/************/
			// UserMaster cm = new UserMaster();

			obsProduto.add(new Produto(rs.getString("nome"), rs.getString("descricao"), rs.getString("preco"), rs.getInt("quantidade")));
			// row.add(obsProduto);
			// obsProduto.add();

		}
		Consulta.table.setItems(obsProduto);
		System.out.println("Concluído");

		/**************/
		// Consulta.setTableItems("Consulta.table", rs.getString("nome"), rs.getString("descricao"), rs.getString("preco"), rs.getInt("quantidade"));

		stmt.close();
		conexao.close();

	} catch (ClassNotFoundException e) {
		System.out.println("Classe não Encontrada");
	} catch (SQLException e) {
		System.out.println("Erro de SQLException -> " + e.getMessage());
	}
	// return obsProduto;

	}

A classe Consulta:

import javafx.application.Application;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.control.cell.*;
import javafx.scene.layout.*;
import javafx.scene.image.*;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.event.*;
import javafx.collections.*;
import java.util.*;

public class Consulta extends Application {
  static Stage stg = new Stage();

  static TextField txtBuscar = new TextField();

  static Label lblProduto = new Label("PRODUTO \n\n");
  static Label lblDescricao = new Label("DESCRIÇÃO \n\n");
  static Label lblPreco = new Label("PREÇO \n\n");
  static Label lblQuantidade = new Label("QTDE \n\n");

  private Button btnBuscar = new Button("Buscar");
  private Button btnCadastrar = new Button("Novo Produto");

  static TableView<Produto> table = new TableView<>();


  private VBox layout = new VBox();
  private HBox hb1 = new HBox();
  private HBox hb2 = new HBox();

  public void start(Stage stage) {

    TableColumn<Produto, String> colProduto = new TableColumn<>("Produto");
    colProduto.setPrefWidth(200);
    colProduto.setCellValueFactory(new PropertyValueFactory<>("nome"));

    TableColumn<Produto, String> colPreco = new TableColumn<>("Preço");
    colPreco.setPrefWidth(100);
    colPreco.setCellValueFactory(new PropertyValueFactory<>("preco"));

    TableColumn<Produto, String> colDescricao = new TableColumn<>("Descrição");
    colDescricao.setPrefWidth(500);
    colDescricao.setCellValueFactory(new PropertyValueFactory<>("descricao"));

    TableColumn<Produto, Integer> colQuantidade = new TableColumn<>("Quantidade");
    colQuantidade.setPrefWidth(100);
    colQuantidade.setCellValueFactory(new PropertyValueFactory<>("quantidade"));


    table.getColumns().addAll(colProduto, colDescricao, colPreco, colQuantidade);
    // table.setItems(this.obterProduto());
    // table.setItems(DataBase.consultarDados());
    table.setEditable(true);

    Scene scn = new Scene(layout, 900, 800);
    stg = stage;
    stg.setScene(scn);
    stg.show();

    layout.getChildren().addAll(table, hb1, hb2);
    hb1.getChildren().addAll(txtBuscar, btnBuscar, btnCadastrar);
    hb2.getChildren().addAll(lblProduto, lblDescricao, lblPreco, lblQuantidade);

    txtBuscar.setPromptText("Nome do Produto");

    btnBuscar.setOnAction(e -> {
      lblProduto.setText("PRODUTO\n\n");
      lblDescricao.setText("DESCRIÇÃO\n\n");
      lblPreco.setText("PRECO\n\n");
      lblQuantidade.setText("QUANTIDADE\n\n");
      DataBase.consultarDados();
    });
    btnCadastrar.setOnAction(e -> new Cadastro().start(Cadastro.stg));
    DataBase.consultarDados();
  }

  //Usando esse acontece o mesmo erro
  public static ObservableList<Produto> obterProduto() {
    ObservableList<Produto> obsProduto = FXCollections.observableArrayList();
    obsProduto.add(new Produto("pa", "da", "RSx", 2));
    obsProduto.add(new Produto("pb", "db", "RSy", 5));
    return obsProduto;
  }


  // public static void setTableItems(String dbNome, String dbDescricao, String dbPreco, int dbQuantidade) {
  //   table.setItems(dbNome, dbDescricao, dbPreco, dbQuantidade);
  // }

}

E a clsse Produto:


public class Produto {

	static String nome;
	static String preco;
	static String descricao;
	static int quantidade;

	public Produto(String nome, String descricao, String preco, int quantidade) {
		this.nome = nome;
		this.descricao = descricao;
		this.preco = preco;
		this.quantidade = quantidade;
	}

	public static String getNome() {
		return nome;
	}
	public static String getPreco() {
		return preco;
	}
	public static String getDescricao() {
		return descricao;
	}
	public static int getQuantidade() {
		return quantidade;
	}

	// public static void preencherTabela(Connection conexao, ObservableList<Produto> lista) {
	// 	//
	// }

}

Se eu tenho por exemplo:

 osbList.add(new Produto( "hd exerno", descricao, preco, quantidade));
 osbList.add(new Produto( "Carregador Portátil", descricao, preco, quantidade));
 osbList.add(new Produto( "Cartao de memoria", descricao, preco, quantidade));

vai aparecer 3 vezes o cartao de memoria

Usando o código abaixo aparecem quanto items na table? e quantos são iguais?

Uma dica sobre o método consultarDados: O método deve retornar a lista de produtos ao invés de gambiarrescamente acessar a tabela e colocar os dados la. Então lá na sua tela vc chama o método, pega a lista de produtos e seta na tabela. E o nome tbm seria consultarProdutos já que retorna produtos e não dados que é subjetivo.
Outra questão que não ví no seu código, é que toda vez que vc vai consultar e colocar dados na table, recomenda-se limpar a table antes, pra evitar toda vez adicionar os mesmos dados, duplicando.

Obrigado pela ajuda.

aparece o segundo item 2 vezes(pq é o último e tem 2 itens). mas essa lista foi um teste para ver se o problema era com o banco de dados, mas com essa lista também deu o mesmo problema

eu tinha feito ele com retorno:
public static ObservableList<Produto> consultarDados()

e no final retornava a lista:
return obsProdutos

e chamava esse método pela classe Consulta:
table.setItems(DataBase.consultarDados());

mas dava o mesmo problema e alem disso não atualizava a TableView(agora ela atualiza, mas com esse problema do último item repetir)

não duplica quando eu faço uma nova busca, já começa assim.

eu tenho 7 itens na minha tabela, quando inicia o Stage da classe Consulta, aparece certo nas labels, mas na TableView aparece o último item 7 vezes(porque tem 7 itens).

Se eu digitar um nome e clicar em buscar, e o resultado tem 3 itens, a tabbela limpa e aparece só os 3 itens(o último item da busca 3 vezes).

Talvez eu não tenha explicado direito kk, olha no vídeo abaixo:

programa.mkv (780,2 KB)

na Label aparece certo sem repetir, o problema é na ObservableList ou na TableView

Quanto a estrutura do método, não iria resolver, é por boas práticas mesmo.
Quanto ao repetir, pelo comportamento que vc colocou, me parece improvável que repita o último, mais provável que a informação em cada um dos itens seja a referência do último, já que a quantidade sempre é a quantidade correta, mas apenas a informação que está sendo exibida está errada. Pode ser problema de referência de objeto, ou a maneira que vc está buscando as informações dos objetos pras colunas.

Usei o código abaixo pra exibir os dados nas colunas:

TableColumn<Compare, String> col = new TableColumn<>(c.getNome());
                col.setCellValueFactory((TableColumn.CellDataFeatures<Compare, String> p) -> new ObservableValueBase<String>() {
                    @Override
                    public String getValue() {
                          return p.getValue().getChave().toString();
                    }
                });

Obs.: Compare é minha classe entidade, que no seu caso é Produto.

o que seria esse ‘p.getChave()’ ?

eu tentei fazer igual esse video(sem banco de dados), mas o mesmo problema aconteceu, não vi diferença do meu código anterior pro codigo dele:

chave é meu atributo.

Ainda não deu certo, ficou assim:

TableColumn<Produto, String> colProduto = new TableColumn<>("Produto");
    colProduto.setPrefWidth(200);
    colProduto.setCellValueFactory((TableColumn.CellDataFeatures<Produto, String> p) -> new ObservableValueBase<String>() {
      @Override
                    public String getValue() {
                          return Produto.getNome().toString();
                    }
    });

esse método getValue deve ser chamado de onde? ou ele é referente a sua classe?

esse ‘p’ é o nome daCellDataFeatures ou é uma instancia da sua classe?

Agora entendi seu problema.

Vc deve usar atributos de instancia não staticos. Toda vez que vc cria um novo Produto vc sobrescreve os valores. Não importa quantos Produtos vc crie, se os atributos são estáticos o mesmo valor vale pra todas instancias.

1 curtida

Man, vc me ajudou MUITO, vc nao tem noção, valeu mesmo.:grin:

mas eu não sabia que métodos e variáveis estáticas sobreescreviam, por isso tava dando erro kkk

agora tá funcionando direitinho