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: 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:
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.
– wryel
I don’t think it’s right, if it wouldn’t take one goes, for the popular vector.
– Carlos Diego
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).
– wryel
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.
– wryel
@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.
– Carlos Diego