Solucionado (ver solução)
Solucionado
(ver solução)
7
respostas

Dúvida no PutMapping

Estou desenvolvendo um projeto com base nas aulas do curso e meu método de atualização (PutMapping) não atualiza e retorna o erro "Not Found". Se alguém puder clarear as minhas ideias, eu ficaria grato!

Classe Controller:

package com.minascafe.api.controllers;

import com.minascafe.api.entities.FichaProdutor;
import com.minascafe.api.record.DadosAtualizacaoFichaProdutor;
import com.minascafe.api.record.DadosCadastroFichaProdutor;
import com.minascafe.api.record.DadosListagemFichaProdutor;
import com.minascafe.api.repositories.FichaProdutorRepository;
import jakarta.transaction.Transactional;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController //Endpoint (página web) de Controller
@RequestMapping(value = "produtor") //Define a url da classe
public class FichaProdutorController {
    @Autowired
    private FichaProdutorRepository prod; //Injetando o Repository como sendo um atributo

//    @Autowired
//    FichaProdutorService ficha;

    @GetMapping
    public Page<DadosListagemFichaProdutor>Listar(Pageable paginacao){
        return prod.findAll(paginacao).map(DadosListagemFichaProdutor::new);
    }

    @RequestMapping(value = "/nome/{nome}") //Retorna uma ficha de produtor em BUSCA POR NOME
      public ResponseEntity<FichaProdutor> buscar(@PathVariable String nome){ //PathVariable obtém o conteúdo que vem após a última barra e trata a requisição
      FichaProdutor obj = prod.findByNome(nome);
      return ResponseEntity.ok().body(obj);
    }

    @RequestMapping(value = "/id/{id}") //Retorna uma ficha de produtor em BUSCA POR UM ID
    public ResponseEntity<FichaProdutor> retornar(@PathVariable int id){ //PathVariable obtém o conteúdo que vem após a última barra e trata a requisição
    FichaProdutor fic = prod.findById(id);
    return ResponseEntity.ok().body(fic);
    }
    @PostMapping
    @Transactional //Unidade de trabalho isolada que leva o banco de dados de um estado consistente a outro estado consistente
    public void cadastrar(@RequestBody @Valid DadosCadastroFichaProdutor fp) {
      prod.save(new FichaProdutor(fp));

    }

    @PutMapping(value ="/{nome}")
    @Transactional
    public void atualizar (@RequestBody @Valid DadosAtualizacaoFichaProdutor fb){
        var produtor = prod.findByNome(fb.nome());
        produtor.atualizarInformacoes(fb);
    }
}

Classe Repository:

package com.minascafe.api.repositories;
//@author Edson Ferreira Barbosa

import com.minascafe.api.entities.FichaProdutor;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.transaction.annotation.Transactional;

@Transactional
public interface FichaProdutorRepository extends JpaRepository<FichaProdutor, Integer>{

    FichaProdutor findById(int Id); //SELECT * FROM FichaProdutor WHERE Id = this.Id
    FichaProdutor findByNome(String nome); //SELECT * FROM FichaProdutor WHERE nome = this.nome
    FichaProdutor findByApelido(String apelido); //SELECT * FROM FichaProdutor WHERE apelido = this.apelido
    FichaProdutor findByCpf(String cpf); //SELECT * FROM FichaProdutor WHERE cpf = this.cpf
    FichaProdutor findByLote(String lote); //SELECT * FROM FichaProdutor WHERE lote = this.lote
}

Classe Service:

package com.minascafe.api.services;
//@author Edson Ferreira Barbosa

import java.util.Optional;

import com.minascafe.api.entities.FichaProdutor;

public interface FichaProdutorService { //Lógica de negócios da aplicação

    /**
     * Retorna a ficha de um produtor dado um id
     *
     * @param Id
     * @return Ficha Produtor
     * @author Edson
     */
    Optional<FichaProdutor> buscarPorId(int Id);

    /**
     * Retorna a ficha de um produtor dado um nome
     *
     * @param nome
     * @return Ficha Produtor
     * @author Edson
     */
    Optional<FichaProdutor> buscarPorNome(String nome);

    /**
     * Retorna a ficha de um produtor dado um apelido
     *
     * @param apelido
     * @return Ficha Produtor
     * @author Edson
     */
    Optional<FichaProdutor> buscarPorApelido(String apelido);

    /**
     * Retorna a ficha de um produtor dado um cpf
     *
     * @param cpf
     * @return Ficha Produtor
     * @author Edson
     */
    Optional<FichaProdutor> buscarPorCpf(String cpf);

    /**
     *
     * @param lote
     * @return Ficha Produtor
     * @author Edson
     */
    Optional <FichaProdutor> buscarPorLote(String lote);

    /**
     * Remove um produtor da base de dados
     *
     * @param nome
     */
    void remover(String nome);
}
7 respostas

Classe Entity:

package com.minascafe.api.entities;
//@author Edson Ferreira Barbosa

import java.io.Serializable;
import java.time.LocalDate;
import com.minascafe.api.record.DadosAtualizacaoFichaProdutor;
import com.minascafe.api.record.DadosCadastroFichaProdutor;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.*;

@Entity
@Table(name = "ficha_produtor") //Define o nome da tabela no banco em que a entity representa (em caso de não ser o mesmo nome da Entity)
@Getter //Gera os métodos getters
@Setter //Gera os métodos setters
@ToString //Mostra os atributos da classe
@NoArgsConstructor //Gera o construtor default, sem argumentos (parâmetros)
@AllArgsConstructor //Gera um construtor que recebe todos os campos
@EqualsAndHashCode //Verifica se valor/tipo de objetos são iguais e gera referência (hash) sobre o lote
//O lombok gera os códigos em tempo de compilação

public class FichaProdutor implements Serializable{

    private static final long serialVersionUID = -7197449617554309251L;

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)//Gera valores de maneira crescente iniciando pelo valor 1
    private int id;//visibilidade - tipo - nome

    private String lote;
    private String nome;
    private String apelido;
    private String cpf;
    private String telefone;
    private LocalDate data;
    private String entrada_saida;
    private int renda;
    private float humidade;
    private float valor_total;
    private String banco;
    private String agencia;
    private String operacao;
    private String tipo_conta;
    private String numero_conta;
    private String nome_correntista;
    private String chave_pix;
    private Integer saldo_duro_sacos;
    private Float saldo_duro_quilos;
    private Integer saldo_riado_sacos;
    private Float saldo_riado_quilos;
    private Integer saldo_rio_sacos;
    private Float saldo_rio_quilos;
    private Integer saldo_escolha_sacos;
    private Float saldo_escolha_quilos;
    private Integer saldo_mooca_sacos;
    private Float saldo_mooca_quilos;
    private Float preco;

    public FichaProdutor(DadosCadastroFichaProdutor fp) {
        this.lote = fp.lote();
        this.nome = fp.nome();
        this.apelido = fp.apelido();
        this.cpf = fp.cpf();
        this.telefone = fp.telefone();
        this.data = fp.data();
        this.entrada_saida = fp.entrada_saida();
        this.renda = fp.renda();
        this.humidade = fp.humidade();
        this.valor_total = fp.valor_total();
        this.banco = fp.banco();
        this.agencia = fp.agencia();
        this.operacao = fp.operacao();
        this.tipo_conta = fp.tipo_conta();
        this.numero_conta = fp.numero_conta();
        this.nome_correntista = fp.nome_correntista();
        this.chave_pix = fp.chave_pix();
        this.saldo_duro_sacos = fp.saldo_duro_sacos();
        this.saldo_duro_quilos = fp.saldo_duro_quilos();
        this.saldo_riado_sacos = fp.saldo_riado_sacos();
        this.saldo_riado_quilos = fp.saldo_riado_quilos();
        this.saldo_rio_sacos = fp.saldo_rio_sacos();
        this.saldo_rio_quilos = fp.saldo_rio_quilos();
        this.saldo_escolha_sacos = fp.saldo_escolha_sacos();
        this.saldo_escolha_quilos = fp.saldo_escolha_quilos();
        this.saldo_mooca_sacos = fp.saldo_mooca_sacos();
        this.saldo_mooca_quilos = fp.saldo_mooca_quilos();
        this.preco = fp.preco();
    }

    public void atualizarInformacoes(DadosAtualizacaoFichaProdutor fb) {

        if(fb.lote() != null){
          this.lote = fb.lote();
        }
        if(fb.data() != null){
          this.data = fb.data();
        }
        if(fb.nome() != null){
          this.nome = fb.nome();
        }
        if(fb.cpf() != null){
            this.cpf = fb.cpf();
        }
        if(fb.telefone() != null){
            this.telefone = fb.telefone();
        }
        if(fb.banco() != null){
            this.banco = fb.banco();
        }
        if(fb.agencia() != null){
            this.agencia = fb.agencia();
        }
        if(fb.operacao() != null){
            this.operacao = fb.operacao();
        }
        if(fb.numero_conta() != null){
            this.numero_conta = fb.numero_conta();
        }
        if(fb.nome_correntista() != null){
            this.nome_correntista = fb.nome_correntista();
        }
        if(fb.chave_pix() != null){
            this.chave_pix = fb.chave_pix();
        }
        if(fb.renda() != null){
            this.renda = fb.renda();
        }
        if(fb.entrada_saida() != null){
            this.entrada_saida = fb.entrada_saida();
        }
        if(fb.humidade() != null){
            this.humidade = fb.humidade();
        }        
    }
}

Oi Edson!

Sua anotação @PutMapping está assim:

@PutMapping(value ="/{nome}")

Mas esse parâmetro nome não está sendo recebido, então acredito que você deveria remover o parâmetro e deixar assim:

@PutMapping

Mas eu preciso atualizar o registro a partir de um nome fornecido. Nesse caso eu não deveria receber o nome pela url?

Acredito que o meu controller é que não está tratando isso, não seria?

@PutMapping(value ="/{nome}")
    @Transactional
    public void atualizar (@RequestBody @Valid DadosAtualizacaoFichaProdutor fb){
        var produtor = prod.findByNome(fb.nome());
        produtor.atualizarInformacoes(fb);
    }

Entendi. Pelo seu código você já recebe o nome dentro do DadosAtualizacaoFichaProdutor, então não precisa passar o nome na url.

Ok Rodrigo, eu removi (value ="/{nome}") de @PutMapping, mas continua retornando (no Insomnia) a seguinte mensagem:

{
    "timestamp": "2023-05-19T13:24:25.166+00:00",
    "status": 404,
    "error": "Not Found",
    "message": "No message available",
    "path": "/nome"
}

Estou um pouco confuso, mas como eu gostaria de atualizar um determinado registro de produtor, eu não deveria passar o "nome" do mesmo para encontrar o registro desejado e posteriormente alterá-lo?

solução!

O problerma agora é com a url da requisição. Altera no Insomnia para a url ser http://localhost:8080/produtor

Manda aqui tbm um print da requisição no Insomnia

Era isso mesmo Rodrigo, atualizou perfeitamente o registro. Muito obrigado!