One to many XML mapping in Hibernate
One to many relationship states that a single instance of an entity is associated with multiple instances of the another entity. In other words, each record in one of the tables is associated with multiple records in the other table.
Let us check out how we can define such relationship in Hibernate through XML mapping file.
1. Entity Relationship Diagram
Assuming that we have the student and department tables created in database, below is the Entity Relationship diagram of the student and department tables in the MySQL database.
2. Maven Dependency
Let’s first setup the pom.xml file in our maven project.
Make sure we have the following dependencies added to our pom.xml file.
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.30</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>4.3.5.Final</version> </dependency>
3. Hibernate Configuration setup
Make sure we have the hibernate.cfg.xml file configured and added to the project structure in the classpath.
<?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- Database connection settings --> <property name="connection.driver_class">com.mysql.jdbc.Driver</property> <property name="connection.url">jdbc:mysql://localhost:3306/sample_db</property> <property name="connection.username">root</property> <property name="connection.password">root</property> <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <property name="hibernate.show_sql">true</property> <mapping resource="Student.hbm.xml" /> <mapping resource="Department.hbm.xml" /> </session-factory> </hibernate-configuration>
4. Entity classes
We have two entities involved in our demo application, student and department, for which we have two tables existing in the database. So we need to create entity classes corresponding to these tables.
Student.java
package com.jcombat.entity; public class Student { private String studentId; private String firstName; private String lastName; private Department department; public String getStudentId() { return studentId; } public void setStudentId(String studentId) { this.studentId = studentId; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public Department getDepartment() { return department; } public void setDepartment(Department department) { this.department = department; } }
Department.java
package com.jcombat.entity; import java.util.Set; public class Department { private String depId; private String depName; private Set<Student> students; public String getDepId() { return depId; } public void setDepId(String depId) { this.depId = depId; } public String getDepName() { return depName; } public void setDepName(String depName) { this.depName = depName; } public Set<Student> getStudents() { return students; } public void setStudents(Set<Student> students) { this.students = students; } }
5. Hibernate Utility class
Create HibernateUtil.java for initial Hibernate configuration which provides us with the SessionFactory isntance.
HibernateUtil.java
package com.jcombat.utility; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; public class HibernateUtil { private static final SessionFactory sessionFactory = buildSessionFactory(); @SuppressWarnings("deprecation") private static SessionFactory buildSessionFactory() { try { return new Configuration().configure().buildSessionFactory(); } catch (Throwable ex) { System.err.println("Initial SessionFactory creation failed." + ex); throw new ExceptionInInitializerError(ex); } } public static SessionFactory getSessionFactory() { return sessionFactory; } }
6. Hibernate mapping XMLs
Create the hibernate mapping file for each of the entities.
Student.hbm.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.jcombat.entity"> <class name="Student" table="student"> <id name="studentId" column="ID"> <generator class="native" /> </id> <property name="firstName" column="FNAME" /> <property name="lastName" column="LNAME" /> <many-to-one name="department" class="com.jcombat.entity.Department" fetch="select"> <column name="DEPT_ID" not-null="true" /> </many-to-one> </class> </hibernate-mapping>
Department.hbm.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.jcombat.entity"> <class name="Department" table="department"> <id name="depId" column="DEPT_ID"> <generator class="native" /> </id> <property name="depName" column="DEP_NAME" /> <set name="students" table="student" inverse="true" cascade="save-update" lazy="true" fetch="select"> <key> <column name="DEPT_ID" not-null="true" /> </key> <one-to-many class="com.jcombat.entity.Student" /> </set> </class> </hibernate-mapping>
Note that we have used Set to map students associated with a department.
The “Cascade” keyword is often used in the collection mapping to manage the state of the collection automatically. So if there is a set of Students associated with a particular Department and we persist the state of the Department object, all the associated child Student objects also get persisted automatically, thus saving the manual effort to persist them individually. The same is going to happen for our current example.
7. Final Project Structure
Refer to the below project structure once we are done with all the above steps.
7. Execution
We are almost done. The only part remaining is to create the client class from where we will be executing our application. So let’s create a MainApp client class.
MainApp.java
package com.jcombat.hibernate; import java.util.HashSet; import java.util.Set; import org.hibernate.Session; import org.hibernate.SessionFactory; import com.jcombat.entity.Department; import com.jcombat.entity.Student; import com.jcombat.utility.HibernateUtil; public class MainApp { public static void main(String[] args) { SessionFactory sf = HibernateUtil.getSessionFactory(); Session session = sf.openSession(); session.beginTransaction(); Department department = new Department(); department.setDepName("Electronics"); Student student1 = new Student(); student1.setFirstName("Abhimanyu"); student1.setLastName("Prasad"); student1.setDepartment(department); Student student2 = new Student(); student2.setFirstName("Abhishek"); student2.setLastName("Kumar"); student2.setDepartment(department); Set<Student> studSet = new HashSet<Student>(); studSet.add(student1); studSet.add(student2); department.setStudents(studSet); session.save(department); session.getTransaction().commit(); session.close(); } }
Right click on the class and run it as ‘Java Application’. We see the following entries logged into the IDE console.
Hibernate: insert into department (DEP_NAME) values (?) Hibernate: insert into student (FNAME, LNAME, DEPT_ID) values (?, ?, ?) Hibernate: insert into student (FNAME, LNAME, DEPT_ID) values (?, ?, ?)
Verify the individual tables in the database for added entries.
Reference: | One to many XML mapping in Hibernate from our JCG partner Abhimanyu Prasad at the jCombat blog. |