Hi all,
We have seen one-to-one unidirectional, bidirectional, one-to-many unidirectional, bidirectional and many-to-one unidirectional, bidirectional mappings in previous posts. Here we talk about many-to-many unidirectional mapping using annotations. So let’s start.
Here we gonna see a many-to-many relationship between “Course” and “Student”, ie., “many courses will have many students, the same student can be enrolled in many courses”.
In the following example, Course is the parent entity and Student is the child entity. Our mapping flows from Course to Student.
Since the relation is unidirectional, the child details can be obtained by fetching parent details, but the reverse is not possible.
Here’s the parent entity class, Course.java
package com.hibernateApp.entity; import java.io.Serializable; import java.util.List; import javax.persistence.*; @Entity public class Course implements Serializable { private long id; private String name; private List students; @Id @GeneratedValue public long getId() { return id; } public String getName() { return name; } @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL) @JoinTable(name = "Enrollment", joinColumns = { @JoinColumn(name = "Course_Id", insertable = false, updatable = false, nullable = false)}, inverseJoinColumns = { @JoinColumn(name = "Student_Id", insertable = false, nullable = false, updatable = false)}) public List getStudents() { return students; } public void setId(long id) { this.id = id; } public void setName(String name) { this.name = name; } public void setStudents(List students) { this.students = students; } }
In the above class, we have created a join table namely “Enrollment”, which maps courses to students.
Here’s the child entity class, Student.java
package com.hibernateApp.entity; import java.io.Serializable; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; @Entity public class Student implements Serializable { private long id; private String name; @Id @GeneratedValue public long getId() { return id; } public String getName() { return name; } public void setId(long id) { this.id = id; } public void setName(String name) { this.name = name; } }
The generic dao class, DAO.java
package com.hibernateApp.dao; import com.hibernateApp.util.HibernateUtil; import org.hibernate.FlushMode; import org.hibernate.Session; public abstract class DAO { private static final ThreadLocal THREAD = new ThreadLocal(); public static Session getSession() { Session session = (Session) DAO.THREAD.get(); if (session == null) { session = HibernateUtil.getSessionFactory().openSession(); DAO.THREAD.set(session); getSession().setFlushMode(FlushMode.COMMIT); } return session; } protected static void begin() { getSession().beginTransaction(); } protected static void commit() { getSession().getTransaction().commit(); } protected static void rollback() { getSession().getTransaction().rollback(); getSession().close(); DAO.THREAD.set(null); } protected static void flush() { getSession().flush(); } protected static void close() { getSession().close(); DAO.THREAD.set(null); } }
The main class, CourseStudent.java. Note that this class extends the above said DAO.java.
package com.hibernateApp.biz; import com.hibernateApp.dao.DAO; import com.hibernateApp.entity.Course; import com.hibernateApp.entity.Student; import java.util.ArrayList; import java.util.List; public class CourseStudent extends DAO { public void save1() throws Exception { try { begin(); Course course = new Course(); course.setName("MCA"); Student student1 = new Student(); Student student2 = new Student(); List students = new ArrayList(); student1.setName("Rahul"); student2.setName("Sachin"); students.add(student1); students.add(student2); course.setStudents(students); getSession().save(course); commit(); } catch (Exception e) { System.out.println(e.getMessage()); rollback(); } finally { flush(); close(); } } public void save2() throws Exception { try { begin(); Course course = new Course(); course.setName("MBA"); List students = getSession().createCriteria(Student.class).list(); course.setStudents(students); getSession().save(course); commit(); } catch (Exception e) { System.out.println(e.getMessage()); rollback(); } finally { flush(); close(); } } public void listCourses() throws Exception { try { begin(); List courses = getSession().createCriteria(Course.class).list(); for (Course course : courses) { System.out.println("Course Id: " + course.getId()); System.out.println("Course Name: " + course.getName()); for (Student student : course.getStudents()) { System.out.println("Student Id: " + student.getId()); System.out.println("Student Name: " + student.getName()); } } commit(); } catch (Exception e) { rollback(); System.out.println(e.getMessage()); } finally { flush(); close(); } } public void deleteOrphan() throws Exception { try { begin(); Course course = (Course) getSession().load(Course.class, new Long(1)); Student student1 = (Student) getSession().load(Student.class, new Long(1)); Student student2 = (Student) getSession().load(Student.class, new Long(2)); course.getStudents().remove(student1); course.getStudents().remove(student2); getSession().delete(course); commit(); } catch (Exception e) { rollback(); System.out.print(e.getMessage()); } finally { flush(); close(); } } public static void main(String[] args) throws Exception { new CourseStudent().listCourses(); } }
When we execute the save1() method, it outputs
Hibernate: insert into Course (name) values (?) Hibernate: insert into Student (name) values (?) Hibernate: insert into Student (name) values (?) Hibernate: insert into Enrollment (Course_Id, Student_Id) values (?, ?) Hibernate: insert into Enrollment (Course_Id, Student_Id) values (?, ?)
And the data will be stored in our database tables.
When we execute the save2() method, it outputs
Hibernate: select this_.id as id2_0_, this_.name as name2_0_ from Student this_ Hibernate: insert into Course (name) values (?) Hibernate: insert into Enrollment (Course_Id, Student_Id) values (?, ?) Hibernate: insert into Enrollment (Course_Id, Student_Id) values (?, ?)
And we will have our tables like this.
The configuration file, hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="hibernate.connection.driver_class">com.microsoft.sqlserver.jdbc.SQLServerDriver</property> <property name="hibernate.connection.url">jdbc:sqlserver://localhost:1433;databaseName=TEST</property> <property name="hibernate.connection.username">sa</property> <property name="hibernate.connection.password">password</property> <property name="hibernate.format_sql">true</property> <property name="hibernate.show_sql">true</property> <property name="hibernate.hbm2ddl.auto">update</property> <mapping class="com.hibernateApp.entity.Course"/> <mapping class="com.hibernateApp.entity.Student"/> </session-factory> </hibernate-configuration>
The output of the listCourses() method looks like this.
Hibernate: select this_.id as id1_0_, this_.name as name1_0_ from Course this_ Course Id: 1 Course Name: MCA Hibernate: select students0_.Course_Id as Course1_1_, students0_.Student_Id as Student2_1_, student1_.id as id2_0_, student1_.name as name2_0_ from Enrollment students0_ left outer join Student student1_ on students0_.Student_Id=student1_.id where students0_.Course_Id=? Student Id: 1 Student Name: Rahul Student Id: 2 Student Name: Sachin Course Id: 2 Course Name: MBA Hibernate: select students0_.Course_Id as Course1_1_, students0_.Student_Id as Student2_1_, student1_.id as id2_0_, student1_.name as name2_0_ from Enrollment students0_ left outer join Student student1_ on students0_.Student_Id=student1_.id where students0_.Course_Id=? Student Id: 1 Student Name: Rahul Student Id: 2 Student Name: Sachin
Platform
OS: Windows 7 Enterprise SP 1
IDE: Netbeans 7.1.1
Java: 7 Update 51
Hibernate: 3.2.5
Database: Microsoft SQL Server 2012
Thanks.
I used to be able to find good information from your blog posts.