#java #spring-boot #many-to-many
#java #весенняя загрузка #многие-ко-многим
Вопрос:
У меня есть отношение N: M между 2 сущностями, «Alumno» и «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;
}
Далее AlumnoService
у меня есть следующие два метода:
@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);
}
Согласно напечатанным строкам, все данные получены правильно, и на Postman я получаю правильный ответ:
{
"id": 2,
"name": "Marta",
"dni": "67242062K",
"age": 15,
"cursos": [
{
"id": 3,
"name": "Bootstrap 4",
"length": 11,
"alumnos": []
}
]
}
Это 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);
}
Однако после проверки базы данных общая таблица пуста:
Есть идеи, в чем может быть проблема? Я что-то забыл? Я совершенно новичок в весенних ботинках.
Спасибо вам за ваше время
С наилучшими пожеланиями
Комментарии:
1. Не могли бы вы, пожалуйста, опубликовать свой полный курс обслуживания выпускников?
Ответ №1:
Попробуйте использовать @Transactional
аннотацию из org.springframework.transaction.annotation
пакета и посмотрите, работает ли это.
Вот так:
@Transactional
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);
}
Ответ №2:
Я обнаружил, что проблема заключалась в аннотациях объектов. Вот решение, которое (насколько я знаю) работает:
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<>();
}
Здесь я добавил @JsonIgnore, чтобы избежать рекурсии, приводящей к переполнению стека при отображении списков.
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<>();
}
Здесь я добавил mappedBy
атрибут в @ManyToMany. Это было причиной, по которой она не реплицировалась правильно.