Зарегистрируйтесь, чтобы продолжить обучение

Связь многие ко многим Java: Объектно-ориентированный дизайн

Помимо связи один-ко-многим, очень распространена связь многие-ко-многим. Например, такой связью обладают курсы и пользователи. С одной стороны, пользователь может проходить множество курсов, с другой, курс проходится большим количеством студентов.

Кажется, что такую связь можно реализовать, сделав зависимую сущность коллекцией с обоих концов, со стороны курса и со стороны пользователя.

user.addCourse(course);
user.getCourses();
// или
course.addUser(user);
course.getUsers();

На практике же, такая реализация не позволяет смоделировать нашу предметную область правильно. Когда человек вступает в курс, то у него появляется дата вступления в курс, кроме этого, курс можно закончить, а это обязательно должно быть где-то отражено. Эта информация не относится ни к курсу, ни к пользователю, она относится к их связи.

Такую связь реализуют с помощью введения третьей сущности, которая может и, обычно, содержит какие-то дополнительные данные появляющиеся только во время создания связи. В случае курсов, мы точно хотим знать когда пользователь начал курс и когда он его закончил. Помимо этого мы можем добавить другую информацию, которая привязана именно к связи, а не к пользователю или курсу.

В случае курсов и пользователей, сущность, которая связывает курсы и пользователи можно назвать CourseMember (участник курса). Вот ее код:

import java.time.LocalDate;

import lombok.Getter;
import lombok.Setter;

@Setter
@Getter
public class CourseMember {
    private Course course;
    private User user;

    private LocalDate startedAt;
    private LocalDate finishedAt;
}

И использование:

var course = new Course("Java ООП");
var user = new User("Mila");

var member = new CourseMember();
member.setCourse(course);
member.setUser(user);
member.setStartedAt(LocalDate.now());

Мы связали курсы и пользователей связью многие-ко-многим, при этом получившаяся сущность CourseMember связана с курсом связью один-ко-многим и с пользователем связью один-ко-многим. Визуально это выглядит так.

 +----------------+          +---------------------+          +----------------+
 |      User      |          |    CourseMember     |          |     Course     |
 +----------------+          +---------------------+          +----------------+
 | - attributes   |1        *| - Course            |*        1| - attributes   |
 | - methods      |<---------| - User              |--------->| - methods      |
 +----------------+          | - startedAt         |          +----------------+
                             | - finishedAt        |
                             +---------------------+

Для полной реализации таких связей, нам нужно добавить CourseMember в каждую из зависимых сущностей.

@Setter
@Getter
class User {
    private String name;
    private List<CourseMember> courseMembers;

    public User(String name) {
        this.name = name;
        courseMembers = new ArrayList<>();
    }

    public void addCourseMember(CourseMember courseMember) {
        courseMembers.add(courseMember);
    }

    public void removeCourseMember(CourseMember courseMember) {
        courseMembers.remove(courseMember);
    }

    // другие методы
}

@Setter
@Getter
class Course {
    private String name;
    private List<CourseMember> courseMembers;

    public Course(String name) {
        this.name = name;
        courseMembers = new ArrayList<>();
    }

    public void addCourseMember(CourseMember courseMember) {
        courseMembers.add(courseMember);
    }

    public void removeCourseMember(CourseMember courseMember) {
        courseMembers.remove(courseMember);
    }

    // другие методы
}

class CourseMember {
    private User user;
    private Course course;
    private String role;
    private String enrollmentDate;

    public void setCourse(Course course) {
        this.course = course;
        course.addCourseMember(this);
    }

    public void setUser(User user) {
        this.user = user;
        user.addCourseMember(this);
    }
}

Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff
Рекомендуемые программы
профессия
Программирование на Java, Разработка веб-приложений и микросервисов используя Spring Boot, проектирование REST API
10 месяцев
с нуля
Старт 26 декабря

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»