Many-to-Many Example Hibernate


Many-to-Many Hibernate

There are two styles to maintain association in many-to-many Hibernate – a) using Set and b) using Map.

  1. Many-To-many Relationship: In many-to-many relationship, as the name implies, many records of one table are associated with many records of another table.
  2. Concept: One Student may attend multiple courses and similarly one course may be attended by multiple students. You can say, it is many-to-many as multiple students vs multiple courses. Infact, it is one-to-many relationship. Each record (of a group of multiple records) of one table is associated with multiple records of another table.
  3. Association in tables: studentId and courseId are the primary keys in studentinfo and courseinfo tables. studentId is the foreign key, in courseinfo, associated with courseId. Similarly, courseId is the foreign key, in studentinfo, associated with studentId. This mapping is done with <key> element in mapping table. <key> represents always a foreign key in a database table.
  4. Bean coding: Two beans exist, Student and Course. A Set is created in Student class to which all the courses attended by the student are added. Similarly, another Set is created in Course class to which all the students attending the course are added. Here, Set is preferred to List for the reason one student does not go to the same course twice and similarly one course does not have the same student twice. Instead of Set, List also can be used where applicable in other cases. But one thing must be clear, in many-to-many association, it is a must to use a collection class on both the sides.

Following are the variables declared in Student and Course classes.

Student Course
private short studentId; private short courseId;
private String studentName; private String courseName;
private short marks; private String duration;
private Set courses; private Set students;

Note: As we are not creating tables in advance and we are allowing the Hibernate (hbm2ddl) to create the tables for us, studentId is declared as short (instead of int) as it is converted into number(5) occupying less space. Learn how to use short instead of integer in client program.

Notice that Set exists in both classes. Many-to-many is always bidirectional.

We expect two tables representing two bean classes. You are right. But in many-to-many, we require one extra table that maintains (joins) the data of foreign keys of the two tables. We name this mediator join table as keysinfo.

So, total we have two beans, three tables, two XML files. Let us explore them one by one.

1. Bean Program: Student.java

import java.util.Set;
public class Student 
{
  private short studentId;
  private String studentName;
  private short marks;
  private Set courses;                     // observe Set of courses

  public Student() 
  {
    // TODO Auto-generated constructor stub
  }
  public short getStudentId() 
  {
    return studentId;
  }
  public void setStudentId(short studentId) 
  {
    this.studentId = studentId;
  }
  public String getStudentName() 
  {
    return studentName;
  }
  public void setStudentName(String studentName) 
  {
    this.studentName = studentName;
  }
  public short getMarks() 
  {
    return marks;
  }
  public void setMarks(short marks) 
  {
    this.marks = marks;
  }
  public Set getCourses() 
  {
    return courses;
  }
  public void setCourses(Set courses) 
  {
    this.courses = courses;
  }
}

2. Bean Program: Course.java

import java.util.Set;
public class Course 
{
  private short courseId;
  private String courseName;
  private String duration;
  private Set students;                     // observe Set of students

  public Course() 
  {
    // TODO Auto-generated constructor stub
  }
  public short getCourseId() 
  {
    return courseId;
  }
  public void setCourseId(short courseId) 
  {
    this.courseId = courseId;
  }
  public String getCourseName() 
  {
    return courseName;
  }
  public void setCourseName(String courseName) 
  {
    this.courseName = courseName;
  }
  public String getDuration() 
  {
    return duration;
  }
  public void setDuration(String duration) 
  {
    this.duration = duration;
  }
  public Set getStudents() 
  {
    return students;
  }
  public void setStudents(Set students) 
  {
    this.students = students;
  }
}

3. Configuration XML file: hibernate.cfg.xml





  
    org.hibernate.dialect.Oracle9Dialect
    jdbc:oracle:thin:@localhost:1521:orcl1
    scott
    tiger
    oracle.jdbc.driver.OracleDriver
    SNRaoConnection

    update
    true
 
    
  
 

4. Mapping XML file: Student.hbm.xml



 

  
    
 
    
    
 
    
      
      
    
  

  
    
    
    

    
      
      
    
  

Observe the special join table name, and cascade.


  
  

We have chosen Set to store the courses attended by the student. The join table is keysinfo. <key> means that student_id column of studentinfo should be treated as foreign key. Many-to-Many association of student is with Course. student_id and course_id are to be mapped in keysinfo table.

5. 1st Client Program: InsertClient.java (to insert records in tables)

import java.util.*;
import org.hibernate.*;
import org.hibernate.cfg.*;

public class InsertClient 
{
  public static void main(String[] args) 
  {
    Configuration c = new Configuration();
    c.configure("hibernate.cfg.xml"); 
    SessionFactory sf = c.buildSessionFactory();
    Session s = sf.openSession();        
		 
    Student std1 = new Student();
    std1.setStudentId((short)100);
    std1.setStudentName("S N Rao");
    std1.setMarks((short)45);
		 
    Student std2 = new Student();
    std2.setStudentId((short)101);
    std2.setStudentName("Jyostna");
    std2.setMarks((short)75);
		 
    Course course1 = new Course();
    course1.setCourseId((short) 1234);
    course1.setCourseName("Java");
    course1.setDuration("60 days");
		 
    Course course2 = new Course();
    course2.setCourseId((short) 5678);
    course2.setCourseName("Spring");
    course2.setDuration("30 days");
		 
    Set set1 = new HashSet();
    set1.add(course1);
    set1.add(course2);
		 
    std1.setCourses(set1);
    std2.setCourses(set1);
		 
    Transaction tx = s.beginTransaction();
    s.save(std1);   s.save(std2);
		 
    tx.commit();
    s.close();  sf.close();
    System.out.println("Many To Many is over.");
  }
}

std1.setStudentId((short)100);

The parameter 100 is converted into short as studentId is declared as short in the Student bean program. The whole number, in Java by default, is treated as int and a floating-point number as double.

Number of courses, course1 and course2 are added to the Set object set1. With setCourses() method, the Set set1 is added to Student object. The set1 object takes care of inserting Course object into courseinfo table.

Database table data types created by the Hibernate.

Many-to-Many Example Hibernate

Records entered by Hibernate after executing the client program – InsertClient.java

Many-to-Many Example Hibernate

Console screenshot to know what SQL statements are executed by Hibernate.

Many-to-Many Example Hibernate

6. 2nd Client Program: RetrieveClient.java (to retrieve records from tables)

import java.util.*;
import org.hibernate.*;
import org.hibernate.cfg.*;
public class RetrieveClient 
{
  public static void main(String[] args) 
  {
    Configuration c = new Configuration();
    c.configure("hibernate.cfg.xml"); 
    SessionFactory sf = c.buildSessionFactory();
    Session s = sf.openSession();        
                                                                           
    //  Student std = (Student) s.get(Student.class,new Integer(100));

    Student std = (Student) s.get(Student.class, new Short((short)100));
    System.out.println(std.getStudentId() + ", " + std.getStudentName() + ", " + std.getMarks());
        
    Set mySet = std.getCourses();
    Iterator it = mySet.iterator();
    while(it.hasNext())
    {
      Course c1 = (Course) it.next();
      System.out.println(c1.getCourseId() + ", " + c1.getCourseName() + ", " + c1.getDuration());
    }
        		
    s.close();
    sf.close();
  }
}

// Student std = (Student) s.get(Student.class,new Integer(100)); // general style
Student std = (Student) s.get(Student.class, new Short((short)100));

The general style does not work here as the studentId is declared s short in Student table. Infact, the second parameter of get() method is an object of Serializable. As Short wrapper class is serialized (infact, its super class Number is serialized), it can also be included as parameter.

Many-to-Many Hibernate

7. 3rd Client Program: DeleteClient.java (to retrieve records from tables)

You have seen how to insert and retrieve records in many-to-many association. Now let us write one more program to delete the records. When a student object is deleted, its associated courses also deleted.

import java.util.*;
import org.hibernate.*;
import org.hibernate.cfg.*;
public class DeleteClient 
{
  public static void main(String[] args) 
  {
    Configuration c = new Configuration();
    c.configure("hibernate.cfg.xml"); 
		 
    SessionFactory sf = c.buildSessionFactory();
    Session s = sf.openSession();        
    Transaction tx = s.beginTransaction();

    Student std = (Student) s.load(Student.class, new Short((short)100));
    s.delete(std);

    tx.commit();
    System.out.println("Records deleted.");
    s.close();
    sf.close();
  }
}

Console screenshot to know what SQL statements are called to delete one Student record. Records from keysinfo (join table) are also deleted.

Many-to-Many Example Hibernate

4 thoughts on “Many-to-Many Example Hibernate”

  1. Hello sir,
    here if we delete one record with ‘100’, all the records are deleted including ‘101’ record also and the table is empty .
    could you please tell me the reason or why it happens?

      1. Which means we cant use s.delete(). so then how can we delete only 100’s record. How to use delete Query here?
        could you please explain little bit?

Leave a Comment

Your email address will not be published.