Реализация связи один-ко-многим в Java с помощью Hibernate
Реализация связи один-ко-многим в Java с помощью Hibernate.
Update:
На сайте есть еще один пример один-ко многим для Hibernate. В процессе работы над другими статьями получилось две разных. Поэтому для тех, кому будет что-то непонятно здесь, могут обратиться в другой, почти такой же пример.
Используемые технологии:
Hibernate 5.0.1.Final
Maven 3.2.5
IntelliJ IDEA 14
MySQL 5.6.25
1. Описание задачи
Связь один-ко-многим используется, когда записи из таблицы А может соответствовать 0 или более записей в таблице Б и для каждой записи из Б есть 1 запись таблицы А.
2. Структура проекта
Основа взята из Hibernate – пример отображения один к одному One-To-One. Все настройки остались прежними. В этой части были добавлены несколько таблиц и необходимый Java код, который будет описан в этой статье. Схема таблиц:
В примере будем использовать таблицу контактов и сотрудников. У каждого сотрудника может быть несколько телефонов и email’ов, но каждый телефон и почта могут относится только к одному сотруднику.
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 95 96 97 98 99 100 |
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; //OneToMany Example private Set<ContactsEntity> contacts = new HashSet<>(); @OneToMany(cascade = CascadeType.ALL, mappedBy = "employee") public Set<ContactsEntity> getContacts() { return this.contacts; } public void setContacts(Set<ContactsEntity> contacts) { this.contacts = contacts; } public void addContacts(ContactsEntity contact) { contact.setEmployee(this); this.contacts.add(contact); } @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; } @Column(name = "fk_ad_id", nullable = false, insertable = false, updatable = false) public int getAddressId() { return addressId; } public void setAddressId(int addressId) { this.addressId = addressId; } @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 + '\'' + '}'; } } |
ContactsEntity:
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.*; @Entity @Table(name = "contacts", schema = "", catalog = "relationship") public class ContactsEntity { private int id; private String tel; private String email; //OneToMany Example private EmployeeEntity employee; @ManyToOne @JoinColumn(name = "employee_id", referencedColumnName = "id") public EmployeeEntity getEmployee() { return this.employee; } public void setEmployee(EmployeeEntity employee) { this.employee = employee; } @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 = "tel", nullable = true, insertable = true, updatable = true, length = 50) public String getTel() { return tel; } public void setTel(String tel) { this.tel = tel; } @Basic @Column(name = "email", nullable = true, insertable = true, updatable = true, length = 50) public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public ContactsEntity() { } public ContactsEntity(String tel, String email) { this.tel = tel; this.email = email; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; ContactsEntity that = (ContactsEntity) o; if (id != that.id) return false; if (tel != null ? !tel.equals(that.tel) : that.tel != null) return false; if (email != null ? !email.equals(that.email) : that.email != null) return false; return true; } @Override public int hashCode() { int result = id; result = 31 * result + (tel != null ? tel.hashCode() : 0); result = 31 * result + (email != null ? email.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 |
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.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("LasettName"); ContactsEntity contacts = new ContactsEntity(); contacts.setEmail("info@javastudy.ru"); contacts.setTel("8-800-2000-600"); employee.addContacts(contacts); contacts = new ContactsEntity("mail@javastudy.ru", "8-495-35-35-35"); employee.addContacts(contacts); session.save(employee); tx.commit(); session.close(); } } |
Создаются два контакта, добавляются к сущности EmployeeEntity и сохраняем в базу данных.
Обратите внимание, что контакты добавляются не через setContacts, а addContacts. Посмотрите реализацию этого метода выше.
Результат (сначала была записана запись с одним контактом, потом с двумя):
P.S. в конструкторе new ContactsEntity(«mail@javastudy.ru», «8-495-35-35-35»); перепутал местами переменные 🙂
Исходный код
Hibernate OneToMany src — src
Hibernate OneToMany SQL — база данных с записями
*В исходном коде, доступном для скачивания будет закомментирован код относящийся к варианту один-к-одному (оставил чтобы можно было сравнить реализации). Чтобы не путать читателя, в статье приведен листинг сущностей только с кодом для один-ко-многим.
95 thoughts on “Реализация связи один-ко-многим в Java с помощью Hibernate”
Добавить комментарий
Для отправки комментария вам необходимо авторизоваться.
Великолепно!
Реализовал с PostgeSQL, все работает отлично!
Огромное спасибо!
к сожалению, в чистом виде скачанное с сайта, не заработало, надо будет разбираться
а в идеале было бы неплохо реализовать подобное на примере web-приложения и по шагово
спасибо
Статья классная, но ее нужно откорректировать, куча ошибок:
AppMain:
строка 38 вызывает org.hibernate.NonUniqueObjectException: A different object with the same identifier value was already associated with the session, нужно сделать новый объект и его добавлять в Set пример(ContactsEntity contacts2);
Конструктор класса ContactsEntity указан не верно, нарушен порядок принимаемых параметров;
и по мелочи, такие как неточности в классах Entity
Хотя тут тоже свой плюс, пока ищешь ошибки лучше понимаешь код)
редактор с отступами и списками бесполезен, все равно в бд сохраняет только текст
Ошибся, строка 38 в порядке, забыл в класса ContactsEntity указать @GeneratedValue(strategy = GenerationType.IDENTITY)