JPA - Many-To-Many associations explained
In JPA, a many-to-many association represents a relationship where multiple instances of one entity are associated with multiple instances of another entity. This is typically modeled using a join table that contains foreign keys referencing the primary keys of the two entities involved.
Key Points to Understand
- Cardinality:
- In a many-to-many relationship, each instance of an entity can be related to multiple instances of another entity, and vice versa. For example, a
Student
entity can be associated with multipleCourse
entities, and eachCourse
can have multipleStudent
entities.
- In a many-to-many relationship, each instance of an entity can be related to multiple instances of another entity, and vice versa. For example, a
- Join Table:
- A join table is used to establish the many-to-many relationship in the database. This table holds foreign keys to both entities.
- Owning Side:
- One of the entities is considered the owning side of the relationship. The entity on the owning side typically defines the
@JoinTable
annotation, which specifies the join table and the foreign key columns.
- One of the entities is considered the owning side of the relationship. The entity on the owning side typically defines the
- Bidirectional and Unidirectional Relationships:
- Unidirectional: One entity knows about the relationship, while the other does not. Only one entity will have a reference to the other entity.
- Bidirectional: Both entities know about the relationship. Each entity will have a reference to the other entity, and both will use the
@ManyToMany
annotation.
- Cascade Type and Fetch Type:
- Cascade operations can be applied to propagate operations from one entity to the related entities.
- The default fetch type for
@ManyToMany
isLAZY
, meaning related entities are loaded on demand.
Example
Let’s consider an example where we have two entities: Student
and Course
.
Entity Classes
@Entity
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@ManyToMany
@JoinTable(
name = "student_course",
joinColumns = @JoinColumn(name = "student_id"),
inverseJoinColumns = @JoinColumn(name = "course_id")
)
private List<Course> courses = new ArrayList<>();
// Getters and setters
}
@Entity
public class Course {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
@ManyToMany(mappedBy = "courses")
private List<Student> students = new ArrayList<>();
// Getters and setters
}
Explanation
- Student Entity:
- The
Student
entity has aList<Course>
field annotated with@ManyToMany
, indicating that a student can be enrolled in multiple courses. - The
@JoinTable
annotation specifies the name of the join table (student_course
) and the foreign key columns (student_id
andcourse_id
) that establish the many-to-many relationship.
- The
-
Course Entity:
-
The
Course
entity has aList<Student>
field annotated with@ManyToMany(mappedBy = "courses")
, indicating that each course can have multiple students enrolled. -
The
mappedBy
attribute points to thecourses
field in theStudent
entity, makingStudent
the owning side of the relationship.
-
Database Structure
Student Table
Column Name | Data Type | Constraints |
---|---|---|
id | BIGINT | PRIMARY KEY, AUTO_INCREMENT |
name | VARCHAR | NOT NULL |
-
id
: The primary key for theStudent
table. -
name
: A column to store the name of the student.
Course Table
Column Name | Data Type | Constraints |
---|---|---|
id | BIGINT | PRIMARY KEY, AUTO_INCREMENT |
title | VARCHAR | NOT NULL |
-
id
: The primary key for theCourse
table. -
title
: A column to store the title of the course.
Student_Course Table (Join Table)
Column Name | Data Type | Constraints |
---|---|---|
student_id | BIGINT | FOREIGN KEY REFERENCES Student(id) |
course_id | BIGINT | FOREIGN KEY REFERENCES Course(id) |
-
student_id
: A foreign key referencing theid
column in theStudent
table. -
course_id
: A foreign key referencing theid
column in theCourse
table. -
The combination of
student_id
andcourse_id
forms the composite primary key, ensuring that each pair is unique in the join table.
Example of Table Content
Assume we have the following data in the Student
and Course
entities:
-
Students:
- { id: 1, name: “Alice” }
- { id: 2, name: “Bob” }
-
Courses:
- { id: 101, title: “Mathematics” }
- { id: 102, title: “Physics” }
Student Table
id | name |
---|---|
1 | Alice |
2 | Bob |
Course Table
id | title |
---|---|
101 | Mathematics |
102 | Physics |
Student_Course Table (Join Table)
student_id | course_id |
---|---|
1 | 101 |
1 | 102 |
2 | 101 |
How They Work Together
- The
Student_Course
table’sstudent_id
andcourse_id
columns form a composite key that links students and courses together. - This setup allows multiple students to be associated with multiple courses, enforcing the many-to-many relationship.
Use Cases
- Many-to-many relationships are common in scenarios like students and courses, authors and books, or products and categories where each entity can relate to multiple instances of the other entity.
This relational structure efficiently manages the many-to-many association, ensuring that the relationship is accurately represented and enforced in the database.