Invalid Property 'category.subcategory' of bean class. Error saving user to database

Asked

Viewed 230 times

6

I am developing a web application that has the following mapping: A user has a category; A category has several subcategories; a subcategory has several products. As shown below: inserir a descrição da imagem aqui What I am trying to implement is: when the admin registers a new supplier he will inform the personal data of the supplier and the category of his business and the subcategories of his products. Because when the supplier logs in to the platform, it already brings from the bank the logged-in user and the subcategories corresponding to the user, to register its products, as image below: inserir a descrição da imagem aqui

My user model this:

@Entity
public class Usuario implements UserDetails, Serializable {

private static final long serialVersionUID = 1L;

@Id
@GeneratedValue
private Long id;
@NotBlank(message = "Nome é uma informação obrigatória.")
@Size(min = 2, max = 30)
private String nome;
private String nomeFantasia;
@NotBlank(message = "Rua é uma informação obrigatória.")
private String rua;
@NotBlank(message = "Bairro é uma informação obrigatória.")
private String bairro;
private String complemento;
@NotBlank(message = "Estado é uma informação obrigatória.")
private String estado;
@NotBlank(message = "Cidade é uma informação obrigatória.")
private String cidade;
@NotBlank(message = "É uma informação obrigatória.")
private String cnpjCpf;
private String telefone;
public String categoria;
public Usuario getUsuario() {
    return usuario;
}

public void setUsuario(Usuario usuario) {
    this.usuario = usuario;
}

@NotBlank(message = "E-mail é uma informação obrigatória.")
@Email(message = "Não é um e-mail válido")
private String email;
@NotBlank(message = "Senha é uma informação obrigatória.")
private String senha;

private String foto;
@OneToOne
@JoinColumn(name = "id_categoria", unique = true, nullable = false, updatable = false)
private Usuario usuario;
@ManyToMany
@JoinTable(name = "usuarios_roles", joinColumns = @JoinColumn(name = "usuario_id", referencedColumnName = "email"), inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "nomeRole"))
private List<Role> roles;

public List<Role> getRoles() {
    return roles;
}

GETTERS E SETTERS...

Model Categoria

@Entity
public class Categoria {

@Id
@GeneratedValue
private Long id;
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn(name = "id_usuario")
private Usuario usuario;

@OneToMany
@JoinColumn(name = "subcategoria_id")
private List<Subcategoria> subcategorias;

GETTERS E SETTERS...

Model subcategory:

@Entity
public class Subcategoria {

@Id
@GeneratedValue
private Long id;
@NotBlank(message = "")
private String nome;

@OneToMany(mappedBy = "subcategoria")
public List<Produto> produtos;
@ManyToOne
@JoinColumn(name = "categoria_id")
public Categoria categoria;

GETTERS E SETTERS...

Model products:

@Entity
public class Produto implements Serializable {

private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name="produto_id")
public Subcategoria subcategoria;
GETTERS E SETTERS...

User controller:

@Controller
@RequestMapping("/fornecedor")
public class UsuarioController {

@Autowired
private UsuarioService service;

@RequestMapping("/cadastrarFornecedor")
public ModelAndView cadastrarFornecedor(Usuario usuario) {
    ModelAndView mv = new ModelAndView("fornecedor/form");
    mv.addObject("usuario", usuario);
    return mv;
}
@PostMapping("/save")
public ModelAndView save(@Valid Usuario usuario, String senhaconf, @RequestParam("files[]") MultipartFile[] files, String senha, BindingResult result, RedirectAttributes attributes) {

    System.out.print(usuario);
    if (result.hasErrors() || !senha.equals(senhaconf)) {
        attributes.addFlashAttribute("mensagem", "[Verifique os campos!");
        System.out.println("--------erro ao salvar: " + usuario.getId());
        return cadastrarFornecedor(usuario);
    }
    String foto = files[0].getOriginalFilename();
    usuario.setFoto(foto);
    usuario.setSenha(new BCryptPasswordEncoder().encode(senha));
    service.save(usuario);
    attributes.addFlashAttribute("mensagem", "Evento cadastrado com sucesso!");
    return findAll();
}

Form page:

<section class="forms">
    <form th:object="${usuario}" id="formQuantidade"
        th:action="@{/fornecedor/save}" method="POST"
        enctype="multipart/form-data">
        <!--Input responsável em guardar o id-->

        <div class="container-fluid">
            <th:block th:include="/mensagemValidacao :: mensagem"></th:block>
            <div class="row">
                <input id="id" name="id" type="hidden" th:field="*{id}"
                    th:value="*{id}">
                <div class="col-lg-6">
                    <div class="form-group">
                        <label>Nome do empreendimento:</label> <input type="text"
                            name="nome" th:field="*{nome}" id="inputNome"
                            class="form-control">
                    </div>
                    <div class="form-group">
                        <label>Nome fantasia:</label> <input type="text"
                            name="nomeFantasia" th:field="*{nomeFantasia}"
                            class="form-control" id="inputNomeFantasia">
                    </div>
                    <div class="form-group">
                        <label>Rua:</label> <input type="text" name="rua"
                            th:field="*{rua}" id="inputRua" class="form-control">
                    </div>
                    <div class="form-group">
                        <label>Bairro:</label> <input type="text" name="bairro"
                            th:field="*{bairro}" id="inputBairro" class="form-control">
                    </div>
                    <div class="form-group">
                        <label>Complemento:</label> <input type="text" name="complemento"
                            th:field="*{complemento}" id="inputComplemento"
                            class="form-control">
                    </div>
                    <div class="form-group">
                        <label>Cidade:</label> <input type="text" name="cidade"
                            th:field="*{cidade}" id="inputCidade" class="form-control">
                    </div>
                    <div class="form-group">
                        <label>Estado:</label> <select name="estado" class="form-control"
                            th:field="*{estado}" id="inputEstado">
                            <option th:value="AC">Acre</option>
                            <option value="AL">Alagoas</option>
                            <option value="AP">Amapá</option>
                            <option value="AM">Amazonas</option>
                            <option value="BA">Bahia</option>
                            <option value="CE">Ceará</option>
                            <option value="DF">Distrito Federal</option>
                            <option value="ES">Espírito Santo</option>
                            <option value="GO">Goiás</option>
                            <option value="MA">Maranhão</option>
                            <option value="MT">Mato Grosso</option>
                            <option value="MS">Mato Grosso do Sul</option>
                            <option value="MG">Minas Gerais</option>
                            <option value="PA">Pará</option>
                            <option value="PB">Paraíba</option>
                            <option value="PR">Paraná</option>
                            <option value="PE">Pernambuco</option>
                            <option value="PI">Piauí</option>
                            <option value="RJ">Rio de Janeiro</option>
                            <option value="RN">Rio Grande do Norte</option>
                            <option value="RS">Rio Grande do Sul</option>
                            <option value="RO">Rondônia</option>
                            <option value="RR">Roraima</option>
                            <option value="SC">Santa Catarina</option>
                            <option value="SP">São Paulo</option>
                            <option value="SE">Sergipe</option>
                            <option value="TO">Tocantins</option>
                        </select>
                    </div>
                </div>

                <div class="col-lg-6">
                    <div class="form-group">
                        <label>CPF/CNPJ:</label> <input type="text" placeholder=""
                            id="cpfcnpj" th:field="*{cnpjCpf}" name="cnpjCpf"
                            class="form-control">
                    </div>
                    <div class="form-group">
                        <label>Telefone:</label> <input type="text" placeholder=""
                            id="telefone" th:field="*{telefone}" name="telefone"
                            class="form-control">
                    </div>
                    <div class="form-group">
                        <label>Categoria:</label> <select name="usuario.categoria"
                            class="form-control" th:field="*{usuario.categoria}" id="inputCategoria">
                            <option value="Farmarcias">Farmacias</option>
                            <option value="Lanchonetes">Lanchonetes</option>
                            <option value="Material de construçao">Material de
                                Construçao</option>
                            <option value="Restaurantes">Restaurantes</option>
                            <option value="Pizzarias">Pizzarias</option>

                        </select>
                    </div>
                    <label for="quantidade">Subcategorias</label>
                    <div class="inputs">
                        <input type="text" name="campo[]" class="form-control" th:field="*{categoria.subcategoria}"
                            placeholder=""> <br>
                    </div>
                    <a href="javascript:void(0)" id="adicionarcampo"
                        class="btn btn-sm btn btn-success">Nova subcategoria</a>
                    <div class="form-group">
                        <label>Email:</label> <input type="email" name="email"
                            th:field="*{email}" id="inputEmail" class="form-control"
                            placeholder="[email protected]">
                    </div>
                    <div class="form-group">
                        <label>Senha:</label> <input type="password" name="senha"
                            th:field="*{senha}" id="inputSenha" class="form-control"
                            placeholder="Mínimo 6 caracteres">
                    </div>
                    <div class="form-group">
                        <label>Confirmar senha:</label> <input type="password"
                            placeholder="Mínimo 6 caracteres" name="senhaconf"
                            class="form-control">
                    </div>
                </div>
                <div class="col-lg-12">
                    <button type="submit" class="btn btn-primary">Salvar</button>
                    <button type="reset" class="btn btn-danger"
                        onclick="window.location.href='/fornecedor/lista';">
                        Cancelar</button>
                </div>

            </div>
        </div>

The way he’s doing The following mistake:

org.springframework.beans.NotReadablePropertyException: Invalid property 'categoria.subcategoria' of bean class [com.bigboss.comprafacil.models.Usuario]: Bean property 'categoria.subcategoria' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?

As if I don’t have the gets and sets of subcategories or users, someone can help me?

  • Look at your Exception pointing to "category.subcategory" (in its structure, this bidding does not exist). If you haven’t changed after Spring 3 onwards, when you want to send a list to the backend, the input name needs to be indexed, e.g., category.subcategories[0]. name = "category 1"; category.subcategories[1]. name = "category 2"; category.subcategories[0]. products[0]. name = "Product name 1"; and so on. This way, spring will automatically bidding.

  • I don’t think it’s right, if it wouldn’t take one goes, for the popular vector.

  • If the Names of your form match the structure of your objects in the backend it will already arrive filled in your method. You won’t need a for to fill (unless you’re in the flow of mounting the form on the screen, then you’ll need an indexed one to be able to put the indices in the correct positions).

  • Also confirm the mapping of your entities (in the object User has an association with User saying that the column name is id_category ?), arriving at home if I draw how the form should look and put here.

  • @Onetoone @Joincolumn(name = "id_category", Unique = true, nullable = false, updatable = false) private User user; The numbers in my form are hitting, the doubt is like saving to the bank using the correct name. Type save the logged-in user with the product linked to subcategory which in turn is linked to category.

2 answers

4


I think what is missing is to make category.subcategories (plural) and not category.subcategory (singular)

0

Good afternoon friend, in your Class Category you created this way:

@OneToMany
@JoinColumn(name = "subcategoria_id")
private List<Subcategoria> subcategorias;

All right in this step, already in your Subcategory Class:

@OneToMany(mappedBy = "subcategoria")
public List<Produto> produtos;

You are making a mappedBy for an attribute that does not exist in your code.

To solve your supplier problem see only the data of the same index to you create a "session" and save the user who is using logged in it and thus filter everything that this user can view type:

Usuario usuarioBanco = usuarioDao.get(usuario.id);

Something at this level to filter the session user.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.