-1

I'm seeing some videos about API Rest with Spring Boot and so far I've done some basics and when I tried to increase the complexity I'm getting caught.

My idea is in the Post / class, create a new class with students getting the following json:

{
  "nome": "Primeira Serie - A".
  "alunos": [
    "João",
    "José",
    "Maria"
  ]
}

And return:

{
  "id_classe": 101
}

It happens that it saves the class, but it does not save the students and I have no idea how to show only the id of the class.

I have created the following classes in Java:

Model

Classe.java

package com.example.classe.model;

//Import's suppressed

@Entity
@Table(name = "classe")
public class Classe {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    private String nome;

    @OneToMany(mappedBy = "classe")
    private Set<Aluno> alunos = new HashSet<Aluno>();   

    //Get's e Set's suppressed
}

Aluno.java

package com.example.classe.model;

//Import's suppressed

@Entity
@Table(name = "aluno")
public class Aluno {

    private static int tempID = 0;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;
    private String nome;

    @ManyToOne
    @JoinColumn(name = "id_classe")
    @JsonBackReference
    private Classe classe;

    public Aluno(String nome) {
        tempID++;
        this.id = tempID;
        this.nome = nome;
    }

    public Aluno() {
    }

    //Get's e Set's suppressed  

}

Repository

ClasseRepository.java

package com.example.classe.repository;

//Import's suppressed

@Repository
public interface ClasseRepository extends JpaRepository<Classe, Integer> {

    public List<Classe> findAll();

}

Controller

ClasseController.java

package com.example.classe.controller;

//Import's suppressed

@RestController
@RequestMapping("/classe")
public class ClasseController {

    @Autowired
    private ClasseRepository classeRepo;

    @RequestMapping(method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseEntity<Collection<Classe>> getClasse() {
        return new ResponseEntity<>(classeRepo.findAll(), HttpStatus.OK);
    }

    @RequestMapping(method = RequestMethod.POST)
    public ResponseEntity<?> salvarClasse(@RequestBody Classe classe) {
        return new ResponseEntity<>(classeRepo.saveAndFlush(classe), HttpStatus.CREATED);
    }

}

Am I doing everything wrong or did I not understand the concept? But I wanted to understand how to do it that way.

Thanks in advance.

Cesar Sturion

Cesar Sturion
  • 147
  • 1
  • 9

1 Answers1

1

What you want to achieve is totally doable, but requires several changes. I split my answer into 2 parts:


Save the students

There are several problems with saving:

  1. On POST your incoming json deserialized into objects in which Classe has a reference to Anuli, but Anuli doesn't have a reference toClasse. To check it you can add a break point at the line: return new ResponseEntity<>(... , run in debug mode and check fields of Anuli in Classe. To fix it you can add @JsonManagedReference on aluni field in Classe. Related question

  2. Hibernate can't save referenced objects by default. You have to save them one by one after saving your Classe object or just turn on Cascade persisting. Related question

So, to fix 1 and 2 Classe should have:

  @OneToMany(mappedBy = "classe", cascade = CascadeType.PERSIST)
  @JsonManagedReference
  private Set<Aluno> alunos = new HashSet<Aluno>();
  1. You have to remove custom id generation in Alumi (I am talking about static int tempID). Annotation @GeneratedValue will perfectly generate id for you as soon as you persist an object. This custom generation breaks Hibernate support. I even not talking about that it also breaks the app after restart, not threadsafe etc.

Return id only

On POST returned json represent what was returned in classeRepo.saveAndFlush(classe) so it's an object of Classe.

If you want to return exactly this:

{
    "id_classe": 101
}

Then create new class like this:

 public class ClasseIdVO {
    @JsonProperty("id_casse")
    private Integer id;
 // Constructors, getter, setter

VO - means View Object, so this object only for representation, not for persisting, etc.

You can use field name id_casse, but it's against Java code convention, so better add @JsonProperty.

Also change your saving code to new ClasseIdVO(classeRepo.saveAndFlush(classe).getId())

Or you can just return id as a number: classeRepo.saveAndFlush(classe).getId()

Van0SS
  • 51
  • 1
  • 3