Erro no método, mas quais são?

Bom dia de segunda-feira para todos do Guj.

Meu problema é que eu mando incluir um item de pedido na tabela de itens e uma função localizar não encontra o produto que está cadastrado. Gostaria que alguém me ajudasse a corrigir o código abaixo:

    public boolean localizarProduto(String id_produto) {
        bd = BD.getInstance();
        produto.setId(id_produto);
        sql = "SELECT * FROM produtos WHERE id = ?;";
        try {
            statement = bd.connection.prepareStatement(sql);
            statement.setString(1, produto.getId());
            resultSet = statement.executeQuery();
            if(resultSet.next()) {
                produto.setId(resultSet.getString(1));
                produto.setDescricao(resultSet.getString(2));
                produto.setQuantidade(resultSet.getDouble(3));
                produto.setUnidade(resultSet.getString(4));
                produto.setPreco_venda(resultSet.getDouble(5));
                produto.setPreco_ultima_compra(resultSet.getDouble(6));
                produto.setData_cadastro(resultSet.getString(7));
                return true;
            }
        } catch (SQLException erro) {
            System.out.println("erro: " + erro.toString() + sql + produto.getId());
            return false;
        } finally {
            BD.getInstance().close();
        }
        return false;
    }

Atenciosamente,
Ronaldo

Se você executa esse SELECT diretamente no cliente de seu banco, ele traz algum resultado?

Porque declarou ad variáveis produto, bd, sql, statement e resultSet como sendo de instância?
Deveriam ser variáveis locais.

Se o método se chama localizarProduto ele deveria retornar o Produto localizado e não boolean.

Eu acesso produto em outra classe por isto ele é publica. Mas vou declarar como private as demais variáveis. Porém não entendi como consertar o método com relação a ele não achar um produto que está cadastrado. Qual o erro?

Não questionei a visibilidade da variável produto, questionei o fato de ela ser uma variável de instância, ela está declarada no corpo da classe, mas deveria ser uma variável local, declarada dentro do método.

O mesmo vale para as variáveis bd, sql, statement e resultSet, deveriam ser variáveis locais.

Você verificou no seu banco de dados se tem registros nessa tabela?
Você não usa nenhum cliente de banco de dados para verificar suas tabelas?

1 curtida

Sim, a tabela produtos tem os registros procurados. Eu não entendo. Posso declarar produto, statement e resultSet dentro do construtor? E produto é público mas statement e resultSet são public ou private?

Posta um print-screen com esses registros, faz favor.
Se possível também o CREATE dessa tabela.

Não, pois você vai utilizar eles dentro desse método e não dentro do construtor.
Acho que você está confundindo “declarar” com “inicializar”.

Pergunta:
Você já aprendeu a diferença entre:

  • variável de classe;
  • variável de instância; e
  • variável local?

O que estou orientando é que utilize variáveis locais.

Estou pedindo isso, pois no passado você já teve problemas ao manipular a instância errada ao utilizar variáveis de instância e variáveis de classe.

1 curtida

Não, eu não sei o que é variável de classe, instância e local. Sei apena sobre a visibilidade delas private e public. O que é uma variável de instância, o que é uma variável de classe e o que é uma variável local?

Esse é o print do comando create desta tabela produtos:

image

Esse é um print do conteúdo da tabela produtos:

Como você está chamando o método localizarProduto?

Porque você está alterando o id e outras propriedades do produto dentro do método localizarProduto?

Você já pôs um breakpoint e depurou a execução do método localizarProduto?

Eu imaginei, pois algumas vezes sugeri esse tipo de alteração nos seus códigos e geralmente você ignora.

Pois é, Java possui 4 modificadores de visibilidade e você só conhece 2.

Recomendo que estude um pouco mais o básico de POO.

Acredite, não se aprende simplesmente na tentativa e erro.

Sei que você sempre diz que está aprendendo bastante com esse sistema, mas mesmo assim, de tempo em tempo sempre aparece com as mesmas dúvidas.

Suas dúvidas sempre estão relacionadas a:

  • Não entender o que é classe e o que é objeto.

  • Não entender o que são variáveis locais, de instância e de classe.

  • Não entender como objetos trocam mensagens entre si.

1 curtida
                if(!pedidosDAO.localizarProduto(tfId_produto.getText())) {
                    JOptionPane.showMessageDialog(null, "Produto não cadastrado!");
                    tfId_produto.requestFocus();
                    return;
                }

É desta forma que estou chamando o método localizarProduto().

E porque lá dentro do método localizarProduto você está alterando as propriedades de um atributo produto que pertence ao PedidosDAO?

Outra coisa, seu método se chama localizarProduto, mas ele não retorna um Produto, ele retorna um boolean
Está errado, deveria retornar o Produto encontrado.

Sua classe se chama PedidosDAO mas ela está fazendo consultas na tabela de Produtos?
Deveria se chamar ProdutoDAO.

São esses detalhes que tornam cada vez mais difícil o seu entendimento do que está fazendo e a nossa capacidade em tentar te ajudar.

Você já pôs um breakpoint e depurou a execução do método localizarProduto?
O fato de você não ter respondido, me faz acreditar que ainda não fez isso.

Acho bem possível que o seu método esteja fazendo a consulta, mas provavelmente você está setando os resultados obtidos no objeto Produto errado e por isso acha que não está funcionando.

Staroski, eu fiz uma classe DAO que acessa quatro tabelas. Não sabia que era proibido. Ainda não depurei o programa porque não tive tempo, estava ocupado no médico. O que está ocorrendo é que o programa executa o select mas retorna false, ou seja, não encontra o produto. O método está correto?
Eu não estou conseguindo, também, debugar o método.

Obrigado por tudo,
Ronaldo

Proibido não é, mas fica confuso e é preferível dar nomes coerentes com a finalidade. Nada me impede de chamar uma classe de AbacaxiDAO e ela buscar na tabela de usuários. O programa compila e roda, mas é confuso pra caramba e só vai dificultar a vida de quem for dar manutenção no código (incluindo eu mesmo).

Se a classe se chama PedidosDAO, quem for ler o código já espera que ela busque pedidos (e não produtos, e nem qualquer outra tabela).

Dar nomes que façam sentido facilita muito a vida de quem está programando, inclusive o seu eu-do-futuro (é comum a gente não lembrar do próprio código que fez há semanas/meses/anos atrás).

1 curtida

E você já experimentou rodar esse mesmo SELECT na ferramenta que você usa para consultar seu banco?

Por que não?
O que acontece?

Não consigo te responder se já experimentei o mesmo select. Mas em outras classes funcionou.
Agora já não importa mais porque o método localizarProduto funcionou como num passe de mágica. Não estou conseguindo debugar porque não tem erro, agora.
Queria te agradecer e perguntar porque meu Double.parseDouble() não está funcionando nesta linha de código. Ele não funciona quando o valor não é digitado, ou seja uma string em branco, veja algumas linhas:

                Double preco = Double.parseDouble(tfPreco.getText());
                if(preco == 0) {
                    JOptionPane.showMessageDialog(null, "Preço não pode ser zero!");
                    tfPreco.requestFocus();
                    return;
                }

Veja também a mensagem dizendo que o erro está no parse que esta na classe GuiPedidoCliente e linha 283:

Exception in thread "AWT-EventQueue-0" java.lang.NumberFormatException: empty String
	at java.base/jdk.internal.math.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1842)
	at java.base/jdk.internal.math.FloatingDecimal.parseDouble(FloatingDecimal.java:110)
	at java.base/java.lang.Double.parseDouble(Double.java:651)
	at view.GuiPedidoCliente$7.actionPerformed(GuiPedidoCliente.java:283)

Você pode depurar a hora que bem entender, não precisa estar com erro, basta por um breakpoint e ir executando linha a linha.

Ai, ai, aí, essa teimosia de não ler a documentação dos métodos que utiliza.

Já consultou a documentação para saber o que essa exceção significa?

:person_shrugging:t2:

1 curtida