1

Я только пробую работать с БД, поэтому сильно не ругайтесь.

У меня есть БД, в одной таблице описаны студенты, во второй их группы, причем студент может находиться ни в одной из групп, а может быть сразу в нескольких :

group {
id,
name
}
student {
id, 
name,
group_id 
}

Создал две сущности :

GroupEntity {
    private Long id;
    private String name;
    @OneToMany(mappedBy = "groupEntity")
    private List<StudentEntity> studentList = new ArrayList<>();
}

StudentEntity { private Long id; private String name; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "group_id") private GroupEntity groupEntity;
}

И тут я понял, что что-то не так. По моей структуре БД студент может быть только в одной группе, а сущности вроде как я создал правильно. Как мне исправить структуру БД?

И правильно ли я описал связи таблиц в сущностях?

Вот тут есть пример: Примеры записи аннотаций @OneToMany @OneToOne @ManyToMany Одни в один мой пример : у поста может быть много комментариев (@OneToMany). Как они это реализовали с помощью двух таблиц в БД? И обошлись без ManyToMany.

alex Serg
  • 365
  • 1
  • 9
  • причем студент может находиться ни в одной из групп, а может быть сразу в нескольких Тогда это ни фига не OneToMany. Это чистое ManyToMany, которое решается через связующую таблицу. – Akina Mar 04 '21 at 12:18
  • Не понял, что нужно: нужно, чтобы студент принадлежал только одной группе или к нескольким? – lampa Mar 04 '21 at 12:19
  • 1
    три возможных варианта :ни в одной из групп, в одной, или сразу в нескольких. Скорее всего Akina прав, тут должно быть ManyToMany – alex Serg Mar 04 '21 at 12:22
  • Продублирую сюда, потому не уверен, что вы получили нотификацию... Я прочитал ответ по вашей ссылке, но не нашёл там момента, где oneToMany используется в качестве ManyToMany. Если вы про тот пример, где профессор и студенты, то это обычное OneToMany, студент может относиться только к одному профессору, а к профессору относится несколько студентов. – Zhenyria Mar 04 '21 at 13:11

1 Answers1

2

У вас в данном случае ManyToMany. Необходимо аннотировать классы следующим образом:

GroupEntity {
    @ManyToMany(mappedBy = "groupEntities")
    private Set<StudentEntity> students;
}

StudentEntity { @ManyToMany @JoinTable( name = "student_entities_groups", joinColumns = @JoinColumn(name = "student_entity_id"), inverseJoinColumn = @JoinColumn(name = "group_id") ) private Set<GroupEntity> groupEntities;
}

Вам потребуется три таблицы для такой связи. Одна для студентов, вторая для групп, а третья будет соединять их. Этой таблицей в данном случае является student_entities_groups. Эта таблица будет содержать две колонки: id студента и id группы (обратите внимание, что у записей в таблице связей не будет собственных id, только FK на связываемые сущности).

При работе с сущностями, участвующими в отношениях ManyToMany, могут возникать некоторые интересные моменты. Подробнее об этом в моём ответе к другому вопросу. Если в двух словах, то несмотря на то, что в ManyToMany формально обе сущности имеют одинаковые права в отношении друг-друга, фактически владельцем связи является та сущность, в которой находится аннотация @JoinTable.

Zhenyria
  • 2,141
  • 2
  • 16
  • 47
  • @alexSerg я прочитал ответ по вашей ссылке, но не нашёл там момента, где oneToMany используется в качестве ManyToMany. Если вы про тот пример, где профессор и студенты, то это обычное OneToMany, студент может относиться только к одному профессору, а к профессору относится несколько студентов. – Zhenyria Mar 04 '21 at 13:10
  • Посмотрите пожалуйста я правильно исправил структуру БД и сущности в соответствии с вашим ответом. – alex Serg Mar 04 '21 at 13:30
  • @alexSerg если в остальных местах ошибок нет, то должно работать. Только зачем вы в student_entities_groups сделали отдельные колонки для fk? group_id и student_id это и есть FK. У вас в итоге должно быть только две колонки. В остальном верно. И откатите свой вопрос именно к состоянию вопроса, т.к. вопросы не предназначены для уточнения. Задавайте уточнения в комментариях. – Zhenyria Mar 04 '21 at 13:41
  • Я просто посмотрел ваш вопрос, на который вы ссылку кинули и там тоже в связной таблице сначала ключи указаны а потом fk для них – alex Serg Mar 05 '21 at 10:53
  • @alexSerg это просто синтаксис в PostgreSQL такой. FOREIGN KEY (student_id) REFERENCES students (id) ON DELETE CASCADE - сначала пишу FOREIGN KEY, потом его указываю в скобках, а потом пишу, куда он ссылается и на какую колонку – Zhenyria Mar 05 '21 at 11:46
  • но я так понимаю .что эта строка создает поле student_id в таблице CREATE TABLE students_courses ( student_id INTEGER NOT NULL, ... ); а вот тут уже создается сам FOREIGN KEY: FOREIGN KEY (student_id) REFERENCES students (id) ON DELETE CASCADE, – alex Serg Mar 05 '21 at 11:49
  • @alexSerg ну да. Как бы в строке, которая начинается с FOREIGN KEY происходит маппинг колонки на стороннюю колонку. – Zhenyria Mar 05 '21 at 12:03