Объект не сохраняется немедленно в Spring Boot @PostMapping ()

#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-запроса, вместо него создайте новый класс виртуальной машины и сопоставьте класс виртуальной машины с новым объектом. Вы должны создать экземпляр новой сущности, это даст вам действительный идентификатор для вашей таблицы.

Пример:

  1. AppointmentVM.java
     public class AppointmentVM {
        private Long studentId;
        private Long teacherId;
        private Date date;
    }
 
  1. Контроллер
 @PostMapping("")
public ResponseEntity<Appointment> post(@RequestBody AppointmentVM appointmentVm) {
    return ResponseEntity.ok(appointmentService.save(appointmentVm));
}
 
  1. 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);
}
 

Таким образом, экземпляр нового объекта назначения получит сгенерированный идентификатор и должен быть успешно сохранен.