powered by simpleCommunicator - 2.0.49     © 2025 Programmizd 02
Форумы / Java [игнор отключен] [закрыт для гостей] / Spring boot & hibernate: помогите написать правильно @PostMapping
15 сообщений из 15, страница 1 из 1
Spring boot & hibernate: помогите написать правильно @PostMapping
    #39811896
maxim.popov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день.

Пишу обычное CRUD приложение. Не знаю как правильно написать пост запрос.

Само приложение следующее: есть две сущности Instructor и Course. Один инструктор может вести несколько курсов. Нужно обрабатывать пост запрос, в котором перечислены инструктора и курсы, которые они ведут.

Вот сами сущности:

Инструктор:

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
@Entity
@Table(name = "instructor")
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class Instructor {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", columnDefinition = "serial")
    private Long id;

    @Column(name = "name")
    private String name;

    @JsonManagedReference
    @OneToMany(mappedBy = "instructor",
            cascade = {
                    CascadeType.DETACH,
                    CascadeType.MERGE,
                    CascadeType.PERSIST,
                    CascadeType.REFRESH})
    private List<Course> courses = new ArrayList<>();

    public Instructor(String name) {
        this.name = name;
    }
}



Курс:

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
@Entity
@Table(name = "course")
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class Course {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", columnDefinition = "serial")
    private Long id;

    @Column(name = "title")
    private String title;

    @JsonBackReference
    @ManyToOne(cascade = {
            CascadeType.PERSIST,
            CascadeType.MERGE,
            CascadeType.REFRESH,
            CascadeType.DETACH})
    @JoinColumn(name = "instructor_id")
    private Instructor instructor;
}



Вот структура базы данных:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
create table instructor
(
    id   serial      not null,
    name varchar(20) not null,
    primary key (id)
);

create table course
(
    id            serial       not null,
    title         varchar(128) not null,
    instructor_id int default null,
    primary key (id),
    foreign key (instructor_id) references instructor (id)
);



Вот рест контроллер:

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
@RestController
@RequestMapping("v1/instructor")
public class InstructorController {

    private final InstructorService instructorService;
    private final InstructorMapper instructorMapper;

    public InstructorController(InstructorService instructorService, InstructorMapper instructorMapper) {
        this.instructorService = instructorService;
        this.instructorMapper = instructorMapper;
    }

    @GetMapping
    public ResponseEntity<Iterable<Instructor>> getAll() {
        return new ResponseEntity<>(instructorService.getAll(), HttpStatus.OK);
    }

    @GetMapping("{id}")
    public ResponseEntity<Instructor> getInstructor(@PathVariable Long id) throws Exception {
        return instructorService.getById(id)
                .map(i -> new ResponseEntity<>(i, HttpStatus.OK))
                .orElseThrow(() -> new Exception("Not found instructor with id: " + id));
    }

    @PostMapping
    public ResponseEntity<Iterable<Instructor>> postInstructor(@RequestBody Iterable<InstructorDto> dto) {
        Iterable<Instructor> instructors = instructorMapper.iterableToIterable(dto);
        return new ResponseEntity<>(instructorService.saveAll(instructors), HttpStatus.CREATED);
    }
}



Делаю POST запрос вот с таким содержимым:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
[
    {
        "name": "instructor3",
        "courses": [
            {
                "title": "course4"
            }
        ]
    },
    {
        "name": "instructor4",
        "courses": [
            {
                "title": "course5"
            },
            {
                "title": "course6"
            }
        ]
    }
]



Ответ от сервера приходит правильный, т.е. для каждого инструктора и курса назначаются id, в логах hibernate пишет, что происходит вставка в таблицы intructor и course.

Но сами курсы в базу данных записываются не полностью: сохраняет название курса, a instructor_id нет, хотя по идее должен.

Кто подскажет, почему такой пост запрос не пишет в базу данных информацию по курсам?

Полный код можно посмотреть вот здесь .
...
Рейтинг: 0 / 0
Spring boot & hibernate: помогите написать правильно @PostMapping
    #39812005
artas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maxim.popov,

не использовал никогда маппер, но что-то мне подсказывает что просто по названию он не смапит, попробуйде в Джейсон инструктор_ид добавить. Либо, возможно смапит, если поле нейм в инструкторе сделать уникальным
...
Рейтинг: 0 / 0
Spring boot & hibernate: помогите написать правильно @PostMapping
    #39812056
maxim.popov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
artas,

От сервера ответ приходи правильный: и для курсов, и для инструктора назначаются правильные id. Только в таблицу с курсами id инструкторов не пишутся. Почему, я понять не могу.
...
Рейтинг: 0 / 0
Spring boot & hibernate: помогите написать правильно @PostMapping
    #39812078
maxim.popov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Сейчас переписал @PostMapping вот так:

Код: java
1.
2.
3.
4.
5.
6.
7.
    @PostMapping
    public ResponseEntity<Iterable<Instructor>> postInstructor(@RequestBody Iterable<InstructorDto> dto) {
        Iterable<Instructor> instructors = instructorMapper.iterableToIterable(dto);
        instructors.forEach(
                instructor -> instructor.getCourses().forEach(course -> course.setInstructor(instructor)));
        return new ResponseEntity<>(instructorService.saveAll(instructors), HttpStatus.CREATED);
    }



Т.е. "ручками" выставляю инструктора для каждого курса.

Кто подскажет, коректно и допустимо так писать контроллеры, или это натуральный говнокод?
...
Рейтинг: 0 / 0
Spring boot & hibernate: помогите написать правильно @PostMapping
    #39812083
Андрей Панфилов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Spring boot & hibernate: помогите написать правильно @PostMapping
    #39812107
maxim.popov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Андрей Панфилов,

Так как тогда правильно написать @PostMapping для двунаправленной связи @OneToMany?
...
Рейтинг: 0 / 0
Spring boot & hibernate: помогите написать правильно @PostMapping
    #39812111
Андрей Панфилов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maxim.popov,

я ваш вопрос не понимаю. Вы используете три технологии:
- webmvc
- mapstruct
- hibernate

и априори ни одна из них из коробки консистентность двунаправленных связей не поддерживает: webmvc и mapstruct вообще про эту концепцию ничего не знают и там нужно руками делать, т.е. либо писать код в webmvc как вы сделали, либо @AfterMapping в mapstruct, а в хибернейте оно по-умолчанию выключено (включается либо при компиляции либо в рантайме через указание org.hibernate.jpa.AvailableSettings#ENHANCER_ENABLE_ASSOCIATION_MANAGEMENT в свойствах JPA у EMF) - в каком месте это делать решать вам, но сама по себе идея делать двунаправленные связи изначально плохая, со стороны хибера оно полезно только в двух случаях:
- кеширование данных на уровне сессии
- возможность писать более сложные запросы на JPQL и производных
а так оно только вредит
...
Рейтинг: 0 / 0
Spring boot & hibernate: помогите написать правильно @PostMapping
    #39812167
maxim.popov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Андрей Панфиловmaxim.popov,

я ваш вопрос не понимаю. Вы используете три технологии:
- webmvc
- mapstruct
- hibernate

и априори ни одна из них из коробки консистентность двунаправленных связей не поддерживает: webmvc и mapstruct вообще про эту концепцию ничего не знают и там нужно руками делать, т.е. либо писать код в webmvc как вы сделали, либо @AfterMapping в mapstruct, а в хибернейте оно по-умолчанию выключено (включается либо при компиляции либо в рантайме через указание org.hibernate.jpa.AvailableSettings#ENHANCER_ENABLE_ASSOCIATION_MANAGEMENT в свойствах JPA у EMF) - в каком месте это делать решать вам, но сама по себе идея делать двунаправленные связи изначально плохая, со стороны хибера оно полезно только в двух случаях:
- кеширование данных на уровне сессии
- возможность писать более сложные запросы на JPQL и производных
а так оно только вредит

Вопрос очень простой.

Есть две сущности, между которыми двунаправленная связь oneToMany.

Нужно написать @PostMapping, который на вход получает json, и пишет сущности в базу данных. База данных postgres, используем orm hibernate.
Пример json`а и ссылку на git указал в первом посте.

Как бы вы решали данную задачу?
...
Рейтинг: 0 / 0
Spring boot & hibernate: помогите написать правильно @PostMapping
    #39812171
Андрей Панфилов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maxim.popovКак бы вы решали данную задачу?Делать в хибере или mapstruct не особо правильно, потому как будет проблема с безопасностью: как только ваш mapstruct научится обновлять сущности, получится так, что через v1/instructor можно будет у существующих курсов перебивать инструктора - это неправильно. Наиболее предпочтительный вариант - это когда мы с инструктором работаем через один endpoint, а с курсами через другой, т.е. в вашем случае получится два запроса к серверу, если так нельзя, то лично у меня был бы еще один слой, независящий от http.
...
Рейтинг: 0 / 0
Spring boot & hibernate: помогите написать правильно @PostMapping
    #39812174
maxim.popov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Андрей Панфиловmaxim.popovКак бы вы решали данную задачу?Делать в хибере или mapstruct не особо правильно, потому как будет проблема с безопасностью: как только ваш mapstruct научится обновлять сущности, получится так, что через v1/instructor можно будет у существующих курсов перебивать инструктора - это неправильно. Наиболее предпочтительный вариант - это когда мы с инструктором работаем через один endpoint, а с курсами через другой, т.е. в вашем случае получится два запроса к серверу, если так нельзя, то лично у меня был бы еще один слой, независящий от http.

Андрей, а можете подробнее рассказать про способ решения с еще одним слоем, который не зависит от http. Не очень понимаю, как это реализовать.
...
Рейтинг: 0 / 0
Spring boot & hibernate: помогите написать правильно @PostMapping
    #39812178
Андрей Панфилов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maxim.popov,

ну вот есть у вас уже InstructorService, пусть он из DTO преобразует и сохраняет как нужно
...
Рейтинг: 0 / 0
Spring boot & hibernate: помогите написать правильно @PostMapping
    #39812191
maxim.popov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Андрей Панфилов,

Всё, понял.

Вот этот кусок:
Код: java
1.
2.
3.
4.
...
instructors.forEach(
                instructor -> instructor.getCourses().forEach(course -> course.setInstructor(instructor)));
...



перенести на уровень сервиса.
...
Рейтинг: 0 / 0
Spring boot & hibernate: помогите написать правильно @PostMapping
    #39812197
alex55555
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maxim.popovВсё, понял.

Вот этот кусок:
Код: java
1.
2.
3.
4.
...
instructors.forEach(
                instructor -> instructor.getCourses().forEach(course -> course.setInstructor(instructor)));
...


Ну раз понял, тогда можно бы ответит на вопрос - а что делает данный код?
...
Рейтинг: 0 / 0
Spring boot & hibernate: помогите написать правильно @PostMapping
    #39812205
maxim.popov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
alex55555maxim.popovВсё, понял.

Вот этот кусок:
Код: java
1.
2.
3.
4.
...
instructors.forEach(
                instructor -> instructor.getCourses().forEach(course -> course.setInstructor(instructor)));
...


Ну раз понял, тогда можно бы ответит на вопрос - а что делает данный код?

Назначает каждому курсу соответствующего инструктора.
...
Рейтинг: 0 / 0
Spring boot & hibernate: помогите написать правильно @PostMapping
    #39812452
alex55555
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maxim.popovНазначает каждому курсу соответствующего инструктора.
А откуда берётся информация для назначения?

ЗЫ. Интересно, сколько вопросов понадобится, что бы чел. понял очевидное?
...
Рейтинг: 0 / 0
15 сообщений из 15, страница 1 из 1
Форумы / Java [игнор отключен] [закрыт для гостей] / Spring boot & hibernate: помогите написать правильно @PostMapping
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]