Ceci est une ancienne révision du document !
Relations JPA
Les Types de Relations
@OneToMany / @ManyToOne
Cas d'usage : Un auteur a plusieurs livres, un livre a un seul auteur.
Configuration Unidirectionnelle (Rarement recommandée)
@Entity
public class Author {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToMany
@JoinColumn(name = "author_id") // Crée une FK dans Book
private List<Book> books = new ArrayList<>();
}
@Entity
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
// Pas de référence à Author
}
Problème : Génère des UPDATE supplémentaires !
Lancés automatiquement par Hibernate pour mettre à jour la clé étrangère.
Configuration Bidirectionnelle (Recommandée)
@Entity
public class Author {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToMany(
mappedBy = "author", // Référence au champ dans Book
cascade = CascadeType.ALL,
orphanRemoval = true,
fetch = FetchType.LAZY // Par défaut
)
private List<Book> books = new ArrayList<>();
// Méthodes helper pour synchroniser les deux côtés
public void addBook(Book book) {
books.add(book);
book.setAuthor(this);
}
public void removeBook(Book book) {
books.remove(book);
book.setAuthor(null);
}
}
@Entity
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne(
fetch = FetchType.LAZY, // Recommandé
optional = false // NOT NULL en base
)
@JoinColumn(name = "author_id") // Nom de la FK
private Author author;
}
Le côté @ManyToOne est TOUJOURS le propriétaire (owner) de la relation.
Toutes les modifications portant sur cette relation devront se faire côté owner.
@ManyToMany
Cas d'usage : Un étudiant suit plusieurs cours, un cours a plusieurs étudiants.
Configuration Unidirectionnelle
@Entity
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToMany
@JoinTable(
name = "student_course",
joinColumns = @JoinColumn(name = "student_id"),
inverseJoinColumns = @JoinColumn(name = "course_id")
)
private Set<Course> courses = new HashSet<>();
}
@Entity
public class Course {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
// Pas de référence à Student
}
Configuration Bidirectionnelle (✅ Recommandée)
@Entity
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToMany(
cascade = {CascadeType.PERSIST, CascadeType.MERGE},
fetch = FetchType.LAZY
)
@JoinTable(
name = "student_course",
joinColumns = @JoinColumn(name = "student_id"),
inverseJoinColumns = @JoinColumn(name = "course_id")
)
private Set<Course> courses = new HashSet<>();
public void enrollCourse(Course course) {
courses.add(course);
course.getStudents().add(this);
}
public void unenrollCourse(Course course) {
courses.remove(course);
course.getStudents().remove(this);
}
}
@Entity
public class Course {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToMany(mappedBy = "courses")
private Set<Student> students = new HashSet<>();
}