java – Problem writing foreign key to table

Question:

I'm developing a java web project – using Spring, Thymeleaf, Html, Mysql. In this project I have two classes that are related by foreign key. (Technical and Position).

In my view (addicionarTecnico.html) I created a combobox using select to search the list of positions, so far so good, it's showing the list of positions right, but when the position is chosen, it's not sending the information of the selected record to the POST from the Controller (TecnicoController), the Cargo is going empty. I appreciate if anyone can help me. I will put the information below:

TECHNICAL CLASS:

@Entity
@Table(name = "user")
public class Tecnico{

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "user_id")
    private int id;

    @Column(name = "email")
    private String email;

    @Column(name = "password")
    @Transient
    private String password;

    @Column(name = "name")
    private String nome;

    @Column(name = "active")
    private int active;

    @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable(name = "user_role", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
    private Set<Role> roles;

    @Column(name = "cpf")
    private String cpf;

    @Column(name = "matricula")
    private int matricula;

    @Column(name = "perfil")
    private String perfil;

    @Column(name = "status")
    private String status;

    @ManyToOne(cascade=CascadeType.ALL)
    public Cargo cargo;

    // getters e setters

    @Override
    public String toString() {
        return "Tecnico [id=" + id + ", email=" + email + ", password=" + password + ", nome=" + nome + ", active="
                + active + ", roles=" + roles + ", cpf=" + cpf + ", matricula=" + matricula + ", perfil=" + perfil
                + ", status=" + status + ", cargo=" + cargo + "]";
    }

}

POSITION CLASS:

@Entity
@Table(name = "cargo")
public class Cargo {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    public int id;

    @Column(name = "descricao")
    public String descricao;

    @Column(name = "status")
    public String status;

    // getters e setters

    @Override
    public String toString() {
        return "Cargo [id=" + id + ", descricao=" + descricao + ", status=" + status + "]";
    }

}

TECNICOCONTROLLER CLASS (only the GET and POST methods of the view addTecnico.html):

@RequestMapping(value = "/admin/tecnico/adicionarTecnico", method = RequestMethod.GET)
public ModelAndView adicionar() {
    ModelAndView modelAndView = new ModelAndView();
    carregarUsuarioLogado(modelAndView);

    Tecnico tecnico = new Tecnico();

    modelAndView.addObject("tecnico", tecnico);
    modelAndView.setViewName("/admin/tecnico/adicionarTecnico");

    List<Cargo> cargo = cargoService.findAllCargos();

    modelAndView.addObject("cargo", cargo);

    return modelAndView;
}

@RequestMapping(value = "/admin/tecnico/adicionarTecnico", method = RequestMethod.POST)
public ModelAndView adicionar(@Valid Tecnico tecnico, Cargo cargo, BindingResult bindingResult) {
    ModelAndView modelAndView = new ModelAndView();

    carregarUsuarioLogado(modelAndView);
    System.out.println("passou por aqui....");
    Tecnico tecnicoMatricula = tecnicoService.findTecnicoByMatricula(tecnico.getMatricula());
    System.out.println("passou por aqui.xxxx...");

    if (tecnicoMatricula != null) {
        bindingResult.rejectValue("matricula", "error.tecnico", "Esta matrícula já foi cadastrada");
    } 
    System.out.println("passou por aqui.yyyy...");

    Tecnico tecnicoCpf = tecnicoService.findTecnicoByCpf(tecnico.getCpf());

    if (tecnicoCpf != null) {
        bindingResult.rejectValue("cpf", "error.tecnico", "Este CPF já foi cadastrado");
    } 
    System.out.println("passou por aqui..zzzz..");

    Tecnico tecnicoEmail = tecnicoService.findTecnicoByEmail(tecnico.getEmail());

    if (tecnicoEmail != null) {
        bindingResult.rejectValue("email", "error.tecnico", "Este email já foi cadastrado");
    }
    System.out.println("passou por aqui..vvvvv..");

    if (!ValidarCpf.validarCpf(tecnico.getCpf())) {
        bindingResult.rejectValue("cpf", "error.tecnico", "Este cpf é inválido");
    }
    System.out.println("passou por aqui..cccc..");

    if (bindingResult.hasErrors()) {
        modelAndView.setViewName("/admin/tecnico/adicionarTecnico");
    } else {        

        System.out.println(" id do cargo" + cargo.id); ////cargo.id com valor vazio
        System.out.println(" id do cargoxxx" + cargo); ////cargo com valor vazio
        System.out.println(" tecnico " + tecnico);
        //tecnico.setCargo(cargo);
        tecnico.setPassword("smas1234");
        System.out.println("passou por aqui..bbbbb..");

        //tecnicoService.saveTecnico(tecnico);

        System.out.println("passou por aqui...ttttt.");

        modelAndView.addObject("successMessage", "Técnico cadastrado com sucesso!");
        System.out.println("passou por aqui..rrrr..");

        //modelAndView.addObject("tecnico", new Tecnico());
    }
    return modelAndView;
}

TECHNICAL ADDITIONAL VIEW (combobox select only)

        <div class="box-body">                              
            <div class="form-group col-md-4">
                                          <label for="exampleInputEmail">Cargos *</label> 
                  <select class="form-control" th:field="*{cargo.id}">
                                    <option th:each="cargo : ${cargo}" 
                                         th:value="${cargo.id}" th:selected="selected"
                                         th:utext="${cargo.descricao}"/>
                                         </select>
            </div>
         </div> 

Answer:

Ideally, you would have posted your form tags, as this influences how data is sent, but basically, your form should look like this:

<form action="#" th:action="@{/admin/tecnico/adicionarTecnico}" th:object="${tecnico}" method="post">

And in your controller, you only receive the technical object:

@RequestMapping(value = "/admin/tecnico/adicionarTecnico", method = RequestMethod.POST)
public ModelAndView adicionar(@Valid Tecnico tecnico, BindingResult bindingResult) {

Then you will be able to access the job id via the technical object: tecnico.getCargo().getId() .

Scroll to Top