Many-to-Many Mapping in Hibernate

When mapping two entities, we annotate both classes as @Entity and the mapping type is specified as @OneToOne, @OneToMany, @ManyToOne or @ManyToMany over the declaration of one entity class in the other entity class. In Many-To-Many mapping, we refer to a collection/list of the entity from another entity and vice versa; and used @ManyToOne annotation on declarations of both entity collections.

We will assume that each course can have many students (many to many), and each student can do many course(many to many). We will create two entity classes, Course and Student and do a many to many mapping from course to student, and again many to many mapping from student to course. If you are not following the tutorials in order, refer to the article http://javajee.com/your-first-hibernate-program for the basic setup including hibernate configuration file. You should replace the user class in the configuration file with both course and student classes as:

<!-- Names the annotated entity class -->

<mapping class="com.javajee.hiberex.dto.Student"/>

<mapping class="com.javajee.hiberex.dto.Course"/>

Else you will get org.hibernate.MappingException: Unknown entity:…

 

Case 1: Many-To-Many

We will have a collection of Courses in Student, annotated using @ManyToMany:

@Entity

public class Student {

  @Id @GeneratedValue

  private int studId;

  private String studName;

  @ManyToMany

  private Collection<Course> courses=new ArrayList<>();

//Getters and setters not shown here; create them manually or generate in eclipse.

}

 

We will have a collection of Student in Course, annotated using @ManyToMany:

@Entity

public class Course {

  @Id @GeneratedValue

  private int courseId;

  private String courseName;

  @ManyToMany

  private Collection<Student> studs=new ArrayList<>();

//Getters and setters not shown here; create them manually or generate in eclipse.

}

 

The modified test class (CourseTest) is as follows:

import org.hibernate.Session;

import org.hibernate.SessionFactory;

import org.hibernate.cfg.Configuration;

import com.javajee.hiberex.dto.Course;

import com.javajee.hiberex.dto.Student;

 

public class CourseTest {

  public static void main(String[] args) {

    Course course = new Course();

    course.setCourseName("C1");

    Student stud1 = new Student();

    stud1.setStudName("Stud1");

    stud1.getCourses().add(course);

    course.getStuds().add(stud1);

    Student stud2 = new Student();

    stud2.setStudName("Stud2");

    stud2.getCourses().add(course);

    course.getStuds().add(stud2);

 

    Configuration configuration = new Configuration();

    configuration.configure();

    ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()

        .applySettings(configuration.getProperties()).buildServiceRegistry();

    SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);

    Session session = sessionFactory.openSession();

    session.beginTransaction();

    session.save(stud1);

    session.save(stud2);

    session.save(course);

    session.getTransaction().commit();

  }

}

 

If you execute the test class, queries executed by hibernate during its execution (as seen in console) is as follows:

Hibernate: insert into Student (studName) values (?)

Hibernate: insert into Student (studName) values (?)

Hibernate: insert into Course (courseName) values (?)

Hibernate: insert into Student_Course (Student_studId, courses_courseId) values (?, ?)

Hibernate: insert into Student_Course (Student_studId, courses_courseId) values (?, ?)

Hibernate: insert into Course_Student (Course_courseId, studs_studId) values (?, ?)

Hibernate: insert into Course_Student (Course_courseId, studs_studId) values (?, ?)

 

Case 2: Many-To-Many with mappedBy

In case of Many-To-One mapping, we cannot eliminate the mapping table; however in the above output there are two mapping tables. This is because when hibernate see one entity class with Many-To-One mapping, it create a mapping table and when it see the second entity class with Many-To-One mapping, it again create another mapping table. Since both mapping table are actually the same, we can tell hibernate not to create two mapping tables, but only one.

You have to use mappedBy attribute with either of the entity tables in a Many-To-Many relationship and specify the reference variable name for the current entity in the referenced entity. But we should only place the mappedBy for one of them; if you place mappedBy for both entities, you will get exception: org.hibernate.AnnotationException: Illegal use of mappedBy on both sides of the relationship:…

In our example, we have to specify mappedBy for the @ManyToMany annotation of Course class and specify the reference variable name used for the Course class in the Student class, which is course.

Our new course class is:

@Entity

public class Course {

  @Id @GeneratedValue

  private int courseId;

  private String courseName;

  @ManyToMany(mappedBy="courses")

  private Collection<Student> studs=new ArrayList<>();

//Getters and setters not shown here; create them manually or generate in eclipse.

}

 

If you execute the same test class, queries executed by hibernate during its execution (as seen in console) is as follows:

Hibernate: insert into Student (studName) values (?)

Hibernate: insert into Student (studName) values (?)

Hibernate: insert into Course (courseName) values (?)

Hibernate: insert into Student_Course (studs_studId, courses_courseId) values (?, ?)

Hibernate: insert into Student_Course (studs_studId, courses_courseId) values (?, ?)

 

Tags: 

Quick Notes Finder Tags

Activities (1) advanced java (1) agile (3) App Servers (6) archived notes (2) Arrays (1) Best Practices (12) Best Practices (Design) (3) Best Practices (Java) (7) Best Practices (Java EE) (1) BigData (3) Chars & Encodings (6) coding problems (2) Collections (15) contests (3) Core Java (All) (55) course plan (2) Database (12) Design patterns (8) dev tools (3) downloads (2) eclipse (9) Essentials (1) examples (14) Exception (1) Exceptions (4) Exercise (1) exercises (6) Getting Started (18) Groovy (2) hadoop (4) hibernate (77) hibernate interview questions (6) History (1) Hot book (5) http monitoring (2) Inheritance (4) intellij (1) java 8 notes (4) Java 9 (1) Java Concepts (7) Java Core (9) java ee exercises (1) java ee interview questions (2) Java Elements (16) Java Environment (1) Java Features (4) java interview points (4) java interview questions (4) javajee initiatives (1) javajee thoughts (3) Java Performance (6) Java Programmer 1 (11) Java Programmer 2 (7) Javascript Frameworks (1) Java SE Professional (1) JPA 1 - Module (6) JPA 1 - Modules (1) JSP (1) Legacy Java (1) linked list (3) maven (1) Multithreading (16) NFR (1) No SQL (1) Object Oriented (9) OCPJP (4) OCPWCD (1) OOAD (3) Operators (4) Overloading (2) Overriding (2) Overviews (1) policies (1) programming (1) Quartz Scheduler (1) Quizzes (17) RabbitMQ (1) references (2) restful web service (3) Searching (1) security (10) Servlets (8) Servlets and JSP (31) Site Usage Guidelines (1) Sorting (1) source code management (1) spring (4) spring boot (3) Spring Examples (1) Spring Features (1) spring jpa (1) Stack (1) Streams & IO (3) Strings (11) SW Developer Tools (2) testing (1) troubleshooting (1) user interface (1) vxml (8) web services (1) Web Technologies (1) Web Technology Books (1) youtube (1)