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:
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?
1 curtida