#java #database #spring-boot #rest #backend
#java #База данных #spring-boot #остальное #серверная часть
Вопрос:
Итак, в настоящее время я работаю над серверным приложением Spring Boot, и я заметил, что когда я пытаюсь вернуть сохраненный объект в POST-запросе, элементы, которые связаны с текущим элементом с помощью отношения @OneToMany, не обновляются, пока я нахожусь в этом методе.
Объекты:
@Data
@Entity
@Table(name="APPOINTMENT")
public class Appointment {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@ManyToOne
private Student student;
@ManyToOne
private Teacher teacher;
@Column
private Date date;
}
@Data
@Entity
@Table(name="STUDENT")
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@OneToMany(mappedBy = "student", cascade = CascadeType.REMOVE)
@JsonIgnore
private List<Request> requestList;
@OneToMany(mappedBy = "student", cascade = CascadeType.ALL)
@JsonIgnore
private List<Appointment> appointments;
@OneToMany(mappedBy = "student")
@JsonIgnore
private List<Comment> comments;
@Column(nullable = false, unique = true)
private String neptunCode;
@Column(unique = true)
private String email;
@Column(nullable = false)
private String name;
}
Назначениеконтроллер: (Я создам уровень обслуживания позже)
@PostMapping("")
public ResponseEntity<Appointment> post(@RequestBody Appointment appointment) {
return ResponseEntity.ok(appointmentRepository.save(appointment));
}
Даже когда я пытаюсь сделать что-то подобное, я все равно получаю null для имени и т.д.:
@PostMapping("")
public ResponseEntity<Appointment> post(@RequestBody Appointment appointment) {
appointmentRepository.save(appointment);
return ResponseEntity.ok(appointmentRepository.findById(2).get());
}
(В настоящее время у меня есть 1 элемент, вставленный в базу данных в памяти при ее запуске, поэтому идентификационный номер 2 возвращает этот недавно добавленный элемент)
Это то, что я отправляю в теле запроса POST:
{
"student": {
"id": 1
},
"teacher": {
"id": 1
},
"date": "2050-05-05"
}
И это то, что я получаю обратно:
{
"id": 2,
"student": {
"id": 1,
"neptunCode": null,
"email": null,
"name": null
},
"teacher": {
"id": 1,
"name": null,
"neptunCode": null,
"department": null,
"email": null,
"phoneNumber": null,
"maxStudents": 0
},
"date": "2050-05-05"
}
Когда я делаю еще одно сообщение после этого, предыдущий запрос «регистрируется», и он также отображается правильно, когда я выполняю запрос GET для этого элемента сразу после этого сообщения.
Что еще более странно, так это то, что когда я выполняю запрос PUT и обновляю объект, он работает правильно, и я получаю обратно элемент updatet:
@PutMapping("/{appointmentId}")
public ResponseEntity<Appointment> put(@RequestBody Appointment appointment, @PathVariable Integer appointmentId) {
Optional<Appointment> oAppointment = appointmentRepository.findById(appointmentId);
if (oAppointment.isPresent()) {
appointment.setId(appointmentId);
return ResponseEntity.ok(appointmentRepository.save(appointment));
} else {
return ResponseEntity.notFound().build();
}
}
Я искал решение для этого в Google и обнаружил, что некоторые люди предлагают использовать метод saveAndFlush(), но это также ничего не дает.
Есть ли способ, которым это можно как-то исправить, или просто скажите мне, почему это происходит?
PS.: Я не хочу фактически возвращать весь объект после публикации, но эта проблема теперь беспокоит меня, и я должен знать, почему это происходит …: D
Заранее спасибо!
Комментарии:
1. какой тип репозитория вы расширяете в своем интерфейсе репозитория?
2. @IsaToltar В настоящее время я использую CrudRepository, но я также попробовал это с помощью JpaRespository. Ни то, ни другое не работает.
3. Обновление: я заметил, что вызов метода setId() по какой-то причине вызывает каскадирование. (но я не могу этого сделать, потому что мне нужны автоматически сгенерированные идентификаторы)
Ответ №1:
Прежде всего, вставка новых данных в таблицу непосредственно из контроллера — плохая идея. Для работы с репозиторием вам необходимо реализовать класс обслуживания. Вы выполните @Autowire или любую другую инъекцию репозитория, и из этого класса обслуживания будут вставлены данные. Не отправляйте новый класс объектов из post-запроса, вместо него создайте новый класс виртуальной машины и сопоставьте класс виртуальной машины с новым объектом. Вы должны создать экземпляр новой сущности, это даст вам действительный идентификатор для вашей таблицы.
Пример:
- AppointmentVM.java
public class AppointmentVM {
private Long studentId;
private Long teacherId;
private Date date;
}
- Контроллер
@PostMapping("")
public ResponseEntity<Appointment> post(@RequestBody AppointmentVM appointmentVm) {
return ResponseEntity.ok(appointmentService.save(appointmentVm));
}
- AppointmentService
public Appointment save(AppointmentVM appointmentVm) {
Appointment appointment = new Appointment();
appointment.setStudentId(appointmentVm.getStudentId());
appointment.setTeacherId(appointmentVm.getTeacherId());
appointment.setDate(appointmentVm.getDate());
return appointmentRepository.save(appointment);
}
Таким образом, экземпляр нового объекта назначения получит сгенерированный идентификатор и должен быть успешно сохранен.