Рубрики
Без рубрики

Учебник по аннотациям Hibernate Many to Many

Узнайте, как аннотацию @ManyToMany можно использовать для указания отношений “многие ко многим” в режиме гибернации.

Автор оригинала: Zeger Hendrikse.

1. введение

В этом кратком руководстве мы кратко рассмотрим, как аннотацию @ManyToMany можно использовать для указания этого типа отношений в режиме гибернации.

2. Типичный Пример

Давайте начнем с простой диаграммы отношений сущностей, которая показывает связь “многие ко многим” между двумя сущностями сотрудник и проект:

В этом сценарии любой данный сотрудник может быть назначен нескольким проектам, и в проекте может работать несколько сотрудников, что приводит к связи между ними “многие ко многим”.

У нас есть employee таблица с employee_id в качестве первичного ключа и project таблица с project_id в качестве первичного ключа. Для соединения обеих сторон здесь требуется объединенная таблица employee_project .

3. Настройка базы данных

Предположим, у нас есть уже созданная база данных с именем spring_hibernate_many_to_many.

Нам также необходимо создать таблицы employee и project вместе с таблицей employee_project join с employee_id и project_id в качестве внешних ключей:

CREATE TABLE `employee` (
  `employee_id` int(11) NOT NULL AUTO_INCREMENT,
  `first_name` varchar(50) DEFAULT NULL,
  `last_name` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`employee_id`)
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8;

CREATE TABLE `project` (
  `project_id` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`project_id`)
) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8;

CREATE TABLE `employee_project` (
  `employee_id` int(11) NOT NULL,
  `project_id` int(11) NOT NULL,
  PRIMARY KEY (`employee_id`,`project_id`),
  KEY `project_id` (`project_id`),
  CONSTRAINT `employee_project_ibfk_1` 
   FOREIGN KEY (`employee_id`) REFERENCES `employee` (`employee_id`),
  CONSTRAINT `employee_project_ibfk_2` 
   FOREIGN KEY (`project_id`) REFERENCES `project` (`project_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

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

4. Классы Моделей

Классы моделей Employee и Project должны быть созданы с аннотациями JPA:

@Entity
@Table(name = "Employee")
public class Employee { 
    // ...
 
    @ManyToMany(cascade = { CascadeType.ALL })
    @JoinTable(
        name = "Employee_Project", 
        joinColumns = { @JoinColumn(name = "employee_id") }, 
        inverseJoinColumns = { @JoinColumn(name = "project_id") }
    )
    Set projects = new HashSet<>();
   
    // standard constructor/getters/setters
}
@Entity
@Table(name = "Project")
public class Project {    
    // ...  
 
    @ManyToMany(mappedBy = "projects")
    private Set employees = new HashSet<>();
    
    // standard constructors/getters/setters   
}

Как мы видим, классы Employee и Project ссылаются друг на друга, что означает, что связь между ними является двунаправленной.

Чтобы сопоставить ассоциацию “многие ко многим”, мы используем @ManyToMany , @JoinTable и @JoinColumn аннотации. Давайте рассмотрим их поближе.

Аннотация @ManyToMany используется в обоих классах для создания отношения “многие ко многим” между сущностями.

Эта ассоциация имеет две стороны, то есть сторону владения и обратную сторону. В нашем примере сторона-владелец-это Сотрудник , поэтому таблица соединений указывается на стороне владельца с помощью аннотации @JoinTable в классе Сотрудник . @JoinTable используется для определения таблицы соединений/ссылок. В данном случае это Employee_Project.

Аннотация @JoinColumn используется для указания столбца соединения/связывания с основной таблицей. Здесь столбец соединения является employee_id и project_id является обратным столбцом соединения, так как Project находится на обратной стороне отношения.

В классе Project атрибут mappedBy используется в аннотации @ManyToMany , чтобы указать, что коллекция employees сопоставляется коллекцией projects на стороне владельца.

5. Исполнение

Чтобы увидеть аннотацию “многие ко многим” в действии, мы можем написать следующий тест JUnit:

public class HibernateManyToManyAnnotationMainIntegrationTest {
    private static SessionFactory sessionFactory;
    private Session session;

    // ...

    @Test
    public void givenData_whenInsert_thenCreatesMtoMrelationship() {
        String[] employeeData = { "Peter Oven", "Allan Norman" };
        String[] projectData = { "IT Project", "Networking Project" };
        Set projects = new HashSet<>();

        for (String proj : projectData) {
            projects.add(new Project(proj));
        }

        for (String emp : employeeData) {
            Employee employee = new Employee(emp.split(" ")[0], 
              emp.split(" ")[1]);
 
            assertEquals(0, employee.getProjects().size());
            employee.setProjects(projects);
            session.persist(employee);
 
            assertNotNull(employee);
        }
    }

    @Test
    public void givenSession_whenRead_thenReturnsMtoMdata() {
        @SuppressWarnings("unchecked")
        List employeeList = session.createQuery("FROM Employee")
          .list();
 
        assertNotNull(employeeList);
 
        for(Employee employee : employeeList) {
            assertNotNull(employee.getProjects());
        }
    }

    // ...
}

Мы можем видеть связь “многие ко многим” между двумя сущностями, созданными в базе данных: таблицами employee , project и employee_project с образцами данных, представляющими эту связь.

6. Заключение

В этом руководстве мы рассмотрели, как создавать сопоставления с помощью аннотаций Hibernate “многие ко многим”, что является более удобным аналогом по сравнению с созданием файлов сопоставления XML.

Исходный код этого учебника можно найти на GitHub .