Persistent Hibernate Resource Return

Asked

Viewed 99 times

7

Good afternoon. I would like to understand how to resolve the following issue:

In the project I’m working on, Backend and Frontend are separated. To persist the data I am using Hibernate and to control the connection with BD I have a filter that opens the connection at the beginning of the request and closes it when returning to Replay.

The use case is: In the frontend the user creates a new user relating to a profile. There are already two profiles registered in the BD being:

1 - BASICO
2 - ADMINISTRADOR

User and Profile are represented by different classes:

User class:

@Entity
public class Usuario{
   @Id
   private Long id;
   private String nome;

  @OneToOne
  @JoinColumn(name="id_perfil")
  private Perfil perfil;
}

Class Profile:

@Entity
public class Perfil{
  @Id
  private Long id;
  private String nome;
}

Example of the User Controller class:

public class UsuarioController{

  @PostMapping
  public ResponseEntity<Usuario> salva(@RequestBody Usuario usuario) {

     usuarioDao.salva(usuario);

     return new ResponseEntity<Usuario>(usuario, HttpStatus.CREATED);
  }
}

Example of the User class - method to save:

public void salva(Usuario usuario) {
            // estou utilizando esta estratégia para gerenciar a conexão no BD
    EntityManager manager = JpaUtil.getEntityManager();

    manager.persist(usuario);
}

The JSON received from Frontend to register user is:

{
    "nome":"usuario novo",
    "perfil":{
        "id":1
    }
}

JSON returned from Backend to Frontend is:

{
    "nome":"usuario novo",
    "perfil":{
        "id":1
        "nome":null
    }
}

After the user completes the creation of the new user on the screen, the application directs it to the List Users screen. However, in the frontend when including the new line containing the data of the new user in the list, the profile column will appear the value: null - compatible with what is being returned in JSON.

What is good practice for this case???

Backend also return the profile name in JSON, i.e., before returning the User in Sponse, do the following in the controller class: ?

change in User Return Controller - method to create new user

public class Usuariocontroller{

  @PostMapping
  public ResponseEntity<Usuario> salva(@RequestBody Usuario usuario) {

     Usuario usuario = usuarioDao.salva(usuario);

     Perfil perfil = perfilDao.perfil(usuario.getPertil().getId());

     usuario.setPerfil(perfil);

     return new ResponseEntity<Usuario>(usuario, HttpStatus.CREATED);
  }
}

Frontend should make a new request by passing the created user ID, so that it receives the full object?

  • I don’t quite understand the doubt or problem. You’re trying to understand why the profile name is null in the returned json?

  • Hello Dherik. There are already two profiles registered in the BD being: 1 - BASIC, 2 - ADMINISTRATOR. Since, when creating a user, you don’t need to "create a profile" because it already exists in the BD. When creating a new user, only one relationship is made. Is my doubt clearer? Please reread the session from "What is the good practice for this case???" - Thank you.

  • Use the following relationships HATEOAS would be good practice. In your save you do not need to consult the profile, by default all *ToOne is EAGER, then just give a refresh.The persist should already return the current state of the managed entity, so try returning the user at salva and not void - as Spring Data does, for example.

1 answer

1

From what I understand you want to save the user by passing the id of a new profile, is that right? If so, the value of the name will always be null. @Onetoone by default is EAGER(documentacao Onetoone), then it is no use to load again, as it will always be loaded when the user entity is loaded. I will offer you some suggestions for improvement as you requested:

Suggestions for improvement:

1) Tip: Tidy the method name

     Perfil perfil = perfilDao.perfil(usuario.getPertil().getId()); //O que quer dizer perfil ??
     //Coloque alguma coisa mais clara, por exemplo
     Perfil perfil = perfilDao.recuperPerfil(usuario.getPertil().getId());

Method means an action, so the ideal would be to alter the infinitive, rather than save.

 @PostMapping
  public ResponseEntity<Usuario> **salvar**(@RequestBody Usuario usuario) {...

2) Tip: If it is a relational 1 to 1, then there will always be a user and a profile, right? Wouldn’t it be better to use @Embedded, because their entities are small? Follows documentation: https://docs.jboss.org/hibernate/orm/3.6/reference/en-US/html/mapping.html#Mapping-declaration-Component

3) Tip: If it will always be 1 to 1, the ID MIGHT be the same, then use @Mapsid Follows documentation: https://docs.jboss.org/hibernate/jpa/2.1/api/javax/persistence/MapsId.html

4) Tip: Thinking object-oriented, I believe a user has a profile, but a profile may be tied to multiple users. For example: Maria(1) has the Administrator profile(1), Joao(2) also has the Administrator profile(1). If following this way would change your project a lot, you would first register the Profile and then the user, and it would be a @Manytoone relationship, which is also EAGER by default, and would probably solve your null problem.

5) Last hint: If you save the user and profile together and the mapping is correct, then pass the following in JSON:

{
    "nome":"usuario novo",
    "perfil":{
        "id":1,
        "nome": "Administrador"
    }
}

This way will probably solve the null that is returning.

I suggest you make suggestions for numbers 1,2 and 4.

  • Hello Thiago. Thank you for all the suggestions. About your item 5, you came close to answering my question and in fact, when reading your comments I saw that I did not comment that the profiles are already registered in the comic book. This occurs in the Application Startup, where: 1 - BASICO, 2 - ADMINISTRATOR. Since, when creating a user, you don’t need to "create a profile" because it already exists in the BD. When creating a new user, only one relationship is made.

  • That is why the JSON sent by Frontend is informed only the Profile ID and not the name. And then, my question arises: The Front request, prompts the creation of the user and the Back Sponse, by default, returns the JSON that I specified in the description of the topic.

  • Are your tables being generated by Hibernate? Try to change the mapping to be @Onetoone(fetch = Fetchtype.EAGER, mappedBy="user", optional = true) private Profile profile; E on the profile entity put: @Onetoone private User user;

Browser other questions tagged

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