Différences
Ci-dessous, les différences entre deux révisions de la page.
| Les deux révisions précédentes Révision précédente Prochaine révision | Révision précédente | ||
| framework-web:spring:relations [2025/10/07 15:28] – jcheron | framework-web:spring:relations [2025/10/08 01:24] (Version actuelle) – [Schéma de base de données] jcheron | ||
|---|---|---|---|
| Ligne 1: | Ligne 1: | ||
| ====== Relations JPA ====== | ====== Relations JPA ====== | ||
| - | ===== Les Types de Relations ===== | + | ===== Types de Relations ===== |
| ==== @OneToMany / @ManyToOne ==== | ==== @OneToMany / @ManyToOne ==== | ||
| Ligne 7: | Ligne 7: | ||
| Cas d' | Cas d' | ||
| - | === Configuration Unidirectionnelle (❌ Rarement recommandée) === | + | === Configuration Unidirectionnelle (🟰 Rarement recommandée) === |
| <sxh java> | <sxh java> | ||
| @Entity | @Entity | ||
| Ligne 529: | Ligne 529: | ||
| @Entity | @Entity | ||
| public class Author { | public class Author { | ||
| - | @OneToMany(mappedBy = " | + | @OneToMany(mappedBy = " |
| private List< | private List< | ||
| } | } | ||
| Ligne 536: | Ligne 536: | ||
| public class Book { | public class Book { | ||
| @ManyToOne | @ManyToOne | ||
| - | @JoinColumn(name = " | + | @JoinColumn(name = " |
| private Author author; | private Author author; | ||
| } | } | ||
| Ligne 542: | Ligne 542: | ||
| **En base de données** : | **En base de données** : | ||
| - | <code sql> | + | <sxh sql> |
| CREATE TABLE author ( | CREATE TABLE author ( | ||
| id BIGINT PRIMARY KEY, | id BIGINT PRIMARY KEY, | ||
| Ligne 551: | Ligne 551: | ||
| id BIGINT PRIMARY KEY, | id BIGINT PRIMARY KEY, | ||
| title VARCHAR(255), | title VARCHAR(255), | ||
| - | author_id BIGINT, | + | author_id BIGINT, |
| CONSTRAINT fk_author FOREIGN KEY (author_id) REFERENCES author(id) | CONSTRAINT fk_author FOREIGN KEY (author_id) REFERENCES author(id) | ||
| ); | ); | ||
| - | </code> | + | </sxh> |
| ==== Conséquence : Seul le Owner peut persister la relation ==== | ==== Conséquence : Seul le Owner peut persister la relation ==== | ||
| Ligne 637: | Ligne 637: | ||
| **Problème** : Génère des requêtes supplémentaires ! | **Problème** : Génère des requêtes supplémentaires ! | ||
| - | <code sql> | + | <sxh sql> |
| INSERT INTO author (name) VALUES ('John Doe'); | INSERT INTO author (name) VALUES ('John Doe'); | ||
| INSERT INTO book (title) VALUES ('Book 1'); | INSERT INTO book (title) VALUES ('Book 1'); | ||
| Ligne 645: | Ligne 645: | ||
| UPDATE book SET author_id = 1 WHERE id = 1; | UPDATE book SET author_id = 1 WHERE id = 1; | ||
| UPDATE book SET author_id = 1 WHERE id = 2; | UPDATE book SET author_id = 1 WHERE id = 2; | ||
| - | </code> | + | </sxh> |
| === Configuration Bidirectionnelle (✅ Meilleure perf) === | === Configuration Bidirectionnelle (✅ Meilleure perf) === | ||
| Ligne 666: | Ligne 666: | ||
| **Requêtes optimisées** : | **Requêtes optimisées** : | ||
| - | <code sql> | + | <sxh sql> |
| INSERT INTO author (name) VALUES ('John Doe'); | INSERT INTO author (name) VALUES ('John Doe'); | ||
| INSERT INTO book (title, author_id) VALUES ('Book 1', 1); -- ✅ FK directement | INSERT INTO book (title, author_id) VALUES ('Book 1', 1); -- ✅ FK directement | ||
| INSERT INTO book (title, author_id) VALUES ('Book 2', 1); -- ✅ Pas d' | INSERT INTO book (title, author_id) VALUES ('Book 2', 1); -- ✅ Pas d' | ||
| - | </code> | + | </sxh> |
| ==== ManyToMany : Qui est le owner ? ==== | ==== ManyToMany : Qui est le owner ? ==== | ||
| Ligne 736: | Ligne 736: | ||
| </ | </ | ||
| - | <code sql> | + | <sxh sql> |
| SELECT * FROM book; -- Requête 1 | SELECT * FROM book; -- Requête 1 | ||
| SELECT * FROM author WHERE id = 1; -- Requête 2 | SELECT * FROM author WHERE id = 1; -- Requête 2 | ||
| Ligne 742: | Ligne 742: | ||
| SELECT * FROM author WHERE id = 3; -- Requête 4 | SELECT * FROM author WHERE id = 3; -- Requête 4 | ||
| ... | ... | ||
| - | </code> | + | </sxh> |
| === Solution 1 : JOIN FETCH === | === Solution 1 : JOIN FETCH === | ||
| Ligne 762: | Ligne 762: | ||
| </ | </ | ||
| - | <code sql> | + | <sxh sql> |
| -- ✅ Une seule requête ! | -- ✅ Une seule requête ! | ||
| SELECT b.*, a.* | SELECT b.*, a.* | ||
| FROM book b | FROM book b | ||
| INNER JOIN author a ON b.author_id = a.id; | INNER JOIN author a ON b.author_id = a.id; | ||
| - | </code> | + | </sxh> |
| === Solution 2 : @EntityGraph === | === Solution 2 : @EntityGraph === | ||
| Ligne 793: | Ligne 793: | ||
| </ | </ | ||
| - | <code sql> | + | <sxh sql> |
| SELECT * FROM author; | SELECT * FROM author; | ||
| Ligne 800: | Ligne 800: | ||
| SELECT id FROM author | SELECT id FROM author | ||
| ); | ); | ||
| - | </code> | + | </sxh> |
| ==== LazyInitializationException ==== | ==== LazyInitializationException ==== | ||
| Ligne 1013: | Ligne 1013: | ||
| '' | '' | ||
| - | <code> | + | <sxh bash> |
| # Afficher les requêtes SQL | # Afficher les requêtes SQL | ||
| spring.jpa.show-sql=true | spring.jpa.show-sql=true | ||
| Ligne 1023: | Ligne 1023: | ||
| # Détecter le problème N+1 | # Détecter le problème N+1 | ||
| spring.jpa.properties.hibernate.session.events.log.LOG_QUERIES_SLOWER_THAN_MS=10 | spring.jpa.properties.hibernate.session.events.log.LOG_QUERIES_SLOWER_THAN_MS=10 | ||
| - | </code> | + | </sxh> |