Hibernate – пример отображения многие-ко-многим Many-To-Many
Рассмотрим как реализовать отношение многие-ко-многим с помощью Hibernate.
Используемые технологии:
Hibernate 5.0.1.Final
Maven 3.2.5
IntelliJ IDEA 14
MySQL 5.6.25
1. Описание задачи
Связь многие-ко-многим используется, когда записи из таблицы А может соответствовать 0 или более записей в таблице Б и наоборот для каждой записи из Б есть 0 или более записей таблицы А.
2. Структура проекта
Основа взята из Реализация связи один-ко-многим в Java с помощью Hibernate. Так же рекомендую прочитать Hibernate – быстрый старт. Пример приложения Hello World (там описано подключение Hibernate и ссылка как подключить MySQL к IDEA). Все настройки остались прежними. В этой части были добавлены несколько таблиц и необходимый Java код, который будет описан в этой статье. Схема таблиц:
Мы будем использовать таблицы employee, cars и employee_car для связи первых двух. Каждый сотрудник может водить несколько корпоративных машин и каждая машина может иметь разных водителей.
2.1 pom.xml и hibernate.cfg.xml
pom.xml:
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>ru.javastudy</groupId> <artifactId>ru.javastudy.hibernateStart</artifactId> <version>1.0</version> <properties> <hibernate-version>5.0.1.Final</hibernate-version> </properties> <dependencies> <!--driver for connection to MYSql database --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.34</version> </dependency> <!-- Hibernate --> <!-- to start need only this --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>${hibernate-version}</version> </dependency> <!-- for JPA, use hibernate-entitymanager instead of hibernate-core --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>${hibernate-version}</version> </dependency> <!-- optional --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-osgi</artifactId> <version>${hibernate-version}</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-envers</artifactId> <version>${hibernate-version}</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-c3p0</artifactId> <version>${hibernate-version}</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-proxool</artifactId> <version>${hibernate-version}</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-infinispan</artifactId> <version>${hibernate-version}</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-ehcache</artifactId> <version>${hibernate-version}</version> </dependency> <!--END Hibernate --> </dependencies> </project> |
hibernate.cfg.xml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <property name="connection.url">jdbc:mysql://localhost:3306/relationship</property> <property name="connection.driver_class">com.mysql.jdbc.Driver</property> <!-- NOTE that after automapping with IDEA property username and password will delete --> <!--and will be: Initial SessionFactory failedorg.hibernate.service.spi.ServiceException: Unable to create requested service--> <property name="connection.username">root</property> <property name="connection.password">admin</property> <!-- NOTE that after automapping with IDEA property username and password will delete --> <mapping class="ru.javastudy.hibernate.dao.entities.AddressEntity"/> <mapping class="ru.javastudy.hibernate.dao.entities.EmployeeEntity"/> <!-- DB schema will be updated if needed --> <!-- <property name="hbm2ddl.auto">update</property> --> </session-factory> </hibernate-configuration> |
3. Описание сущностей
EmployeeEntity:
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
package ru.javastudy.hibernate.dao.entities; import javax.persistence.*; import java.util.HashSet; import java.util.Set; @Entity @Table(name = "employee", schema = "", catalog = "relationship") public class EmployeeEntity { private int id; private String firstName; private String lastName; private int addressId; private Set<CarsEntity> cars = new HashSet<>(); @ManyToMany(cascade = CascadeType.ALL) @JoinTable(name = "employee_car", //foreign key for EmployeeEntity in employee_car table joinColumns = @JoinColumn(name = "employee_id"), //foreign key for other side - EmployeeEntity in employee_car table inverseJoinColumns = @JoinColumn(name = "car_id")) public Set<CarsEntity> getCars () { return cars; } public void setCars(Set<CarsEntity> cars) { this.cars = cars; } public void addCar(CarsEntity car) { cars.add(car); } @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id", nullable = false, insertable = true, updatable = true) public int getId() { return id; } public void setId(int id) { this.id = id; } @Basic @Column(name = "firstName", nullable = true, insertable = true, updatable = true, length = 200) public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } @Basic @Column(name = "lastName", nullable = true, insertable = true, updatable = true, length = 200) public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; EmployeeEntity that = (EmployeeEntity) o; if (id != that.id) return false; if (firstName != null ? !firstName.equals(that.firstName) : that.firstName != null) return false; if (lastName != null ? !lastName.equals(that.lastName) : that.lastName != null) return false; return true; } @Override public int hashCode() { int result = id; result = 31 * result + (firstName != null ? firstName.hashCode() : 0); result = 31 * result + (lastName != null ? lastName.hashCode() : 0); return result; } @Override public String toString() { return "EmployeeEntity{" + "id=" + id + ", firstName='" + firstName + '\'' + ", lastName='" + lastName + '\'' + '}'; } } |
CarsEntity:
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
package ru.javastudy.hibernate.dao.entities; import javax.persistence.*; import java.util.HashSet; import java.util.Set; /** * Created by Nick on 18.10.2015. */ @Entity @Table(name = "cars", schema = "", catalog = "relationship") public class CarsEntity { private int id; private Integer year; private String model; private Set<EmployeeEntity> employeeSet = new HashSet<>(); @ManyToMany @JoinTable(name = "employee_car", //foreign key for CarsEntity in employee_car table joinColumns = @JoinColumn(name = "car_id"), //foreign key for other side - EmployeeEntity in employee_car table inverseJoinColumns = @JoinColumn(name = "employee_id")) public Set<EmployeeEntity> getEmployeeSet() { return employeeSet; } public void setEmployeeSet(Set<EmployeeEntity> employeeSet) { this.employeeSet = employeeSet; } @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id", nullable = false, insertable = true, updatable = true) public int getId() { return id; } public void setId(int id) { this.id = id; } @Basic @Column(name = "year", nullable = true, insertable = true, updatable = true) public Integer getYear() { return year; } public void setYear(Integer year) { this.year = year; } @Basic @Column(name = "model", nullable = true, insertable = true, updatable = true, length = 50) public String getModel() { return model; } public void setModel(String model) { this.model = model; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; CarsEntity that = (CarsEntity) o; if (id != that.id) return false; if (year != null ? !year.equals(that.year) : that.year != null) return false; if (model != null ? !model.equals(that.model) : that.model != null) return false; return true; } @Override public int hashCode() { int result = id; result = 31 * result + (year != null ? year.hashCode() : 0); result = 31 * result + (model != null ? model.hashCode() : 0); return result; } } |
4. Тестирование
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
package ru.javastudy.hibernate.main; import org.hibernate.Session; import org.hibernate.Transaction; import ru.javastudy.hibernate.dao.entities.AddressEntity; import ru.javastudy.hibernate.dao.entities.CarsEntity; import ru.javastudy.hibernate.dao.entities.ContactsEntity; import ru.javastudy.hibernate.dao.entities.EmployeeEntity; import ru.javastudy.hibernate.dao.implementations.EmployeeDAOImpl; import ru.javastudy.hibernate.utils.HibernateSessionFactory; import javax.persistence.EntityManager; import javax.persistence.PersistenceUnit; import java.util.List; public class AppMain { @PersistenceUnit static EntityManager emf; public static void main(String[] args) { System.out.println("Hibernate tutorial start"); Session session = HibernateSessionFactory.getSessionFactory().openSession(); EmployeeDAOImpl employeeDAO = new EmployeeDAOImpl(); employeeDAO.setSession(session); Transaction tx = session.beginTransaction(); EmployeeEntity employee = new EmployeeEntity(); employee.setFirstName("FirstName"); employee.setLastName("LastName"); //add first car to employee CarsEntity car = new CarsEntity(); car.setModel("vaz21099"); car.setYear(1991); employee.addCar(car); //add second car to employee car = new CarsEntity(); car.setModel("calina"); car.setYear(2015); employee.addCar(car); session.save(employee); tx.commit(); session.close(); } } |
Создаются две машины, добавляются к сущности EmployeeEntity и сохраняются в базу данных.
Обратите внимание, что контакты добавляются не через setCars, а addCar. Посмотрите реализацию этого метода выше.
Результат:
Исходный код
Hibernate ManyToMany — src
Hibernate ManyToMany SQL — база данных с записями
8