One-to-Many and Many-to-One 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 One-To-Many mapping, we refer to a collection/list of the entity from another entity and mark the reference variable as @OneToMany. The opposite of this relation from the second entity to the first will be Many-To-One and is annotated as @ManyToOne. The example will make things more clear.

We will assume that each course can have many students(one to many), but each student can do only one course(many to one). We will create two entity classes, Course and Student and do a one to one mapping from course to student, and many to one 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:…

 

Basic structure of Student class (without mapping) is:

@Entity

public class Student {

  @Id @GeneratedValue

  private int studId;

  private String studName;

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

}

 

Basic structure of Course class (without mapping) is:

@Entity

public class Course {

  @Id @GeneratedValue

  private int courseId;

  private String courseName;

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

}

 

Case 1: One-To-Many

Add a reference to a collection of students from the course and mark the reference variable as @OneToMany.

@Entity

public class Course {

  @Id @GeneratedValue

  private int courseId;

  private String courseName;

  @OneToMany

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

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

}

 

We can use the below test class for testing:

public class CourseTest {

  public static void main(String[] args) {

    Course course = new Course();

    course.setCourseName("C1");

    Student stud1 = new Student();

    stud1.setStudName("Stud1");

    course.getStuds().add(stud1);

    Student stud2 = new Student();

    stud2.setStudName("Stud2");

    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();

  }

}

 

Queries executed by hibernate during the execution of CourseTest (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 Course_Student (Course_courseId, studs_studId) values (?, ?)

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

 

Case 2: Many-To-One with One-To-Many

Add a reference to the course from the student and mark the reference variable as @ManyToOne in addition to the earlier @OneToMany from course to student.

@Entity

public class Student {

  @Id @GeneratedValue

  private int studId;

  private String studName;

  @ManyToOne

  private Course course;

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

}

 

We can use the below modified test class for testing:

public class CourseTest {

  public static void main(String[] args) {

    Course course = new Course();

    course.setCourseName("C1");

    Student stud1 = new Student();

    stud1.setStudName("Stud1");

    stud1.setCourse(course);

    course.getStuds().add(stud1);

    Student stud2 = new Student();

    stud2.setStudName("Stud2");

    stud2.setCourse(course);

    course.getStuds().add(stud2);

    SessionFactory sessionFactory = new Configuration().configure()

        .buildSessionFactory();

    Session session = sessionFactory.openSession();

    session.beginTransaction();

    session.save(stud1);

    session.save(stud2);

    session.save(course);

    session.getTransaction().commit();

  }

}

 

Queries executed by hibernate during the execution of CourseTest (as seen in console) is as follows:

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

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

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

Hibernate: update Student set course_courseId=?, studName=? where studId=?

Hibernate: update Student set course_courseId=?, studName=? where studId=?

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

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

 

Case 3: One-To-Many / Many-To-One with mappedBy

As you can see from above console outputs, by default during one-to-many and many-to-one, hibernate creates a separate table for mapping details and insert the ids of both the entity tables into it. In case of one-to-one and many-to-one, you don’t actually require a different mapping table. You can have a foreign key reference to one of the table id from the other. We can tell hibernate not to create a separate mapping table, but make use of foreign key reference using the mappedBy parameter of the @One-To-One annotation. You have to specify the reference variable name for the current entity in the referenced entity.

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

New Student class is:

@Entity

public class Course {

  @Id @GeneratedValue

  private int courseId;

  private String courseName;

  @OneToMany(mappedBy="course")

  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 (as in case 2), queries executed by hibernate during its execution (as seen in console) is as follows:

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

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

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

Hibernate: update Student set course_courseId=?, studName=? where studId=?

Hibernate: update Student set course_courseId=?, studName=? where studId=?

 

As you can see there is no separate mapping table now. Now Student has an additional column course_courseId that refers to the primary key of Course table.

 

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)