Hibernate Tutorial
Core Hibernate
Hibernate Mapping
Hibernate Annotations
Hibernate with Spring Framework
Hibernate with Database
Hibernate Log4j
Inheritance Mapping
Many-to-Many mappings are quite common in database design and Hibernate offers a way to represent this relation at the object level. In this tutorial, we'll dive into how to map a many-to-many relationship using Hibernate.
Let's say we have Student
and Course
entities. A student can enroll in multiple courses, and a course can have multiple students.
student
table: To store student information.course
table: To store course details.student_course
table: A join table to map the many-to-many relationship.Ensure you have the necessary dependencies for Hibernate in your project. If you're using Maven, you'd typically include hibernate-core
among others.
@Entity @Table(name="student") public class Student { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name="student_id") private int id; @Column(name="first_name") private String firstName; @Column(name="last_name") private String lastName; @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL) @JoinTable( name = "student_course", joinColumns = @JoinColumn(name = "student_id"), inverseJoinColumns = @JoinColumn(name = "course_id") ) private Set<Course> courses; // constructors, getters, setters... }
@Entity @Table(name="course") public class Course { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name="course_id") private int id; @Column(name="title") private String title; @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL) @JoinTable( name = "student_course", joinColumns = @JoinColumn(name = "course_id"), inverseJoinColumns = @JoinColumn(name = "student_id") ) private Set<Student> students; // constructors, getters, setters... }
@ManyToMany
: This annotation indicates a many-to-many relationship.@JoinTable
: This specifies the join table (or bridge table).name
: Name of the join table.joinColumns
: The column(s) representing the current entity.inverseJoinColumns
: The column(s) representing the opposite side entity.Session session = sessionFactory.getCurrentSession(); session.beginTransaction(); // create courses and students Course tempCourse1 = new Course("Maths"); Course tempCourse2 = new Course("Physics"); Student tempStudent1 = new Student("John", "Doe"); Student tempStudent2 = new Student("Mary", "Public"); // add courses for students tempStudent1.addCourse(tempCourse1); tempStudent1.addCourse(tempCourse2); tempStudent2.addCourse(tempCourse1); // save the students (and this will save the courses because of CascadeType.ALL) session.save(tempStudent1); session.save(tempStudent2); session.getTransaction().commit();
Session session = sessionFactory.getCurrentSession(); session.beginTransaction(); // fetch student with id=1 Student tempStudent = session.get(Student.class, 1); // print courses for that student System.out.println(tempStudent.getCourses()); session.getTransaction().commit();
FetchType.LAZY
: This ensures that the related entities are not loaded unless they're accessed. It's a good practice to use LAZY fetch type for many-to-many mappings to avoid loading everything when it's not needed.
CascadeType.ALL
: This means operations like save, delete, etc., will cascade to the associated entities. If you save a student, its courses get saved, and vice versa.
Mapping many-to-many relationships can be tricky, especially with the need to have a join table. However, Hibernate simplifies the process and abstracts the complexities, making it easy to work with such relationships at the object level. Ensure you understand cascading and fetching strategies to use them effectively in different scenarios.
Configuring many-to-many associations in Hibernate:
many-to-many
element in the Hibernate XML mapping file or using annotations.<!-- XML Mapping --> <many-to-many name="students" class="com.example.Student"> <join-table name="student_course"> <key column="course_id" /> <inverse-key column="student_id" /> </join-table> </many-to-many>
// Annotation Mapping @ManyToMany @JoinTable( name = "student_course", joinColumns = @JoinColumn(name = "course_id"), inverseJoinColumns = @JoinColumn(name = "student_id")) private Set<Student> students;
Mapping many-to-many relationships with Hibernate annotations:
@ManyToMany
annotation on the reference variable in the entity class.@ManyToMany @JoinTable( name = "student_course", joinColumns = @JoinColumn(name = "course_id"), inverseJoinColumns = @JoinColumn(name = "student_id")) private Set<Student> students;
Join table and join columns in Hibernate many-to-many mapping:
@JoinTable
annotation is used to specify the details of the join table, including the join columns.@ManyToMany @JoinTable( name = "student_course", joinColumns = @JoinColumn(name = "course_id"), inverseJoinColumns = @JoinColumn(name = "student_id")) private Set<Student> students;
Lazy loading with many-to-many associations in Hibernate:
fetch = FetchType.LAZY
to enable lazy loading.@ManyToMany(fetch = FetchType.LAZY) @JoinTable( name = "student_course", joinColumns = @JoinColumn(name = "course_id"), inverseJoinColumns = @JoinColumn(name = "student_id")) private Set<Student> students;
Bidirectional many-to-many mapping in Hibernate:
mappedBy
attribute in the @ManyToMany
annotation to establish bidirectional mapping.// In Course class @ManyToMany(mappedBy = "courses") private Set<Student> students; // In Student class @ManyToMany @JoinTable( name = "student_course", joinColumns = @JoinColumn(name = "student_id"), inverseJoinColumns = @JoinColumn(name = "course_id")) private Set<Course> courses;
Cascading operations in Hibernate many-to-many mapping:
cascade
attribute in the @ManyToMany
annotation.@ManyToMany(cascade = CascadeType.ALL) @JoinTable( name = "student_course", joinColumns = @JoinColumn(name = "course_id"), inverseJoinColumns = @JoinColumn(name = "student_id")) private Set<Student> students;
Extra columns in the join table with Hibernate many-to-many:
// JoinTable entity @Entity @Table(name = "student_course") public class StudentCourse { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @ManyToOne @JoinColumn(name = "course_id") private Course course; @ManyToOne @JoinColumn(name = "student_id") private Student student; // Additional columns // ... }
HQL queries for many-to-many associations in Hibernate:
String hql = "FROM Course c JOIN c.students s WHERE s.name = :studentName"; Query query = session.createQuery(hql); query.setParameter("studentName", "John Doe"); List<Course> courses = query.list();