Joint table in many-to-many is not updating



I have a relation N:M between 2 entities, “Alumno” and “Curso”:

Alumno

@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "alumno")
public class Alumno {

    @Id
    @GeneratedValue
    private int id;
    private String name;
    private String dni;
    private int age;

    @ManyToMany(mappedBy = "alumnos", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private List<Curso> cursos;


}

Curso

@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "curso")
public class Curso {
    @Id
    @GeneratedValue
    private int id;
    private String name;
    private int length;

    @ManyToMany
    private List<Alumno> alumnos;
}

On AlumnoService I have the following two methods:

    @Autowired
    private AlumnoRepository repository;

    @Autowired
    private CursoService cursoService;

...
//Non-related stuff
...

    public Alumno updateAlumno(Alumno alumno) {
        Alumno existingAlumno = repository.findById(alumno.getId()).orElse(null);
        existingAlumno.setName(alumno.getName());
        existingAlumno.setDni(alumno.getDni());
        existingAlumno.setAge(alumno.getAge());


        return repository.save(existingAlumno);
    }

    public Alumno insertCurso(int id_alumno, int id_curso) {
        Alumno alumno = repository.findById(id_alumno).orElse(null);
        System.out.println("Found alumno:  => " + alumno.getId() + " " + alumno.getName());
        Curso curso = cursoService.getCursoById(id_curso);
        System.out.println("Found curso:  => " + curso.getId() + " " + curso.getName());
        alumno.getCursos().add(curso);

        System.out.println("========");
        for (Curso c: alumno.getCursos()) {
            System.out.println(c.getId() + " " + c.getName());
        }
        System.out.println("==========");

        return updateAlumno(alumno);
    }

According to the printed lines, all the data is fetch correctly, and on Postman I get a correct answer:

{
    "id": 2,
    "name": "Marta",
    "dni": "67242062K",
    "age": 15,
    "cursos": [
        {
            "id": 3,
            "name": "Bootstrap 4",
            "length": 11,
            "alumnos": []
        }
    ]
}

This is the AlumnoController:

    @Autowired
    private AlumnoService service;

    @PutMapping("/insertCurso/{id_a}/{id_c}")
    public Alumno insertCurso(@PathVariable("id_a") int id_a, @PathVariable("id_c") int id_c) {
        return service.insertCurso(id_a, id_c);
    }

However, upon inspecting the database, the shared table is empty: Description

Any idea on what the issue might be? Did I forget something? I’m completely new to Spring boot.

Thank you for your time

Best regards

Answer

I found the problem was on the annotations of the entities. Here is a solution that (as far as I know) works:

Alumno

@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "alumno")
public class Alumno {

    @Id
    @GeneratedValue
    private int id;
    private String name;
    private String dni;
    private int age;

    @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable(name = "matriculas",
            joinColumns = @JoinColumn(name = "alumno_id"),
            inverseJoinColumns = @JoinColumn(name = "curso_id")
    )
    @JsonIgnore
    private List<Curso> cursos = new ArrayList<>();


}

Here I added the @JsonIgnore to avoid recursion leading to a stack overflow while displaying the lists.

Curso

@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "curso")
public class Curso {
    @Id
    @GeneratedValue
    private int id;
    private String name;
    private int length;

    @ManyToMany(cascade = CascadeType.ALL, mappedBy = "cursos")
    private List<Alumno> alumnos = new ArrayList<>();
}

Here I added the mappedBy attribute to the @ManyToMany. This was the reason it wasn’t replicating correctly.



Source: stackoverflow