Réponds à voix haute ou par écrit avant d’ouvrir la réponse : c’est l’effort de rappel qui fait retenir. Marque ensuite la question « Je savais » ou « À revoir », puis filtre sur « À revoir » pour la prochaine séance. Les marques restent dans ce navigateur.

Rappel actif

Restitue de mémoire, sans support.

  1. Sans regarder : donne le FetchType par défaut des quatre associations, puis la règle qui permet de le retrouver sans l’apprendre par cœur.

  2. Cite les six valeurs de CascadeType et l’opération que chacune propage du parent vers les entités associées. Que se passe-t-il si on ne précise rien ?

  3. Pour chaque mapping du cours, dis ce qui apparaît en base : table de jointure ou colonne clé étrangère, et dans quelle table.

    OneToOne (uni et bi) ; OneToMany unidirectionnelle Entreprise vers Equipe ; ManyToOne unidirectionnelle Equipe vers Entreprise ; OneToMany / ManyToOne bidirectionnelle ; ManyToMany (uni et bi).

Distingue

Deux notions proches : dis ce qui les sépare vraiment.

  1. Entreprise / Equipe : la OneToMany unidirectionnelle et la bidirectionnelle donnent des tables différentes. Lesquelles, et qu’est-ce qui, dans le code, explique cette différence ?

  2. Dans une OneToOne bidirectionnelle Projet / ProjetDetail, quel côté porte mappedBy en Java, et quelle table porte la clé étrangère en base ? Pourquoi ce ne sont pas les mêmes ?

  3. CascadeType.REMOVE et orphanRemoval suppriment tous deux des enfants. Quel événement déclenche chacun ?

  4. LAZY et EAGER : compare-les sur trois critères (moment du chargement, performances, cas d’usage).

  5. Unidirectionnel et bidirectionnel : est-ce une propriété de la base de données ou du code Java ? Appuie-toi sur la ManyToMany Equipe / Projet.

Explique pourquoi

Le mécanisme derrière la règle.

  1. Pourquoi une ManyToMany produit-elle toujours une table de jointure, alors qu’une ManyToOne se contente d’une colonne ?

  2. Pourquoi les associations vers une collection sont-elles LAZY par défaut, et celles vers une seule entité EAGER ?

  3. Dans @OneToMany(mappedBy = "entreprise"), à quoi correspond exactement la chaîne "entreprise" ? Pourquoi pas "entreprise_id_entreprise" ?

  4. Pourquoi, dans une OneToMany / ManyToOne, est-ce la table du côté « Many » (equipe) qui porte la clé étrangère ?

Cas pratique

Choisis et justifie avec les critères du cours.

  1. AutoLoc : une Agence possède plusieurs Vehicule, un véhicule appartient à une seule agence. On veut naviguer dans les deux sens et éviter toute table de jointure. Écris les deux attributs d’association.

  2. Une page liste les 200 entreprises par nom, et chaque entreprise a des centaines d’équipes que la page n’affiche pas. Quel FetchType veux-tu sur Entreprise.equipes, et dois-tu écrire quelque chose pour l’obtenir ?

  3. Règle métier : quand on retire une équipe de la liste d’une entreprise, l’équipe doit disparaître de la base. Mais si on supprime l’entreprise, on doit aussi supprimer toutes ses équipes. Quels réglages faut-il, et pourquoi un seul ne suffit pas ?

  4. On crée un Projet avec un ProjetDetail neuf, puis on sauvegarde uniquement le projet. On veut que le détail soit enregistré du même coup. Qu’ajoutes-tu, et sur quel attribut ?

Trouve l'erreur

Chaque affirmation contient au moins une faute.

  1. « Avec cette configuration, supprimer l’équipe Web ne supprime que l’équipe : les projets sont partagés avec d’autres équipes, ils restent. »

    @ManyToMany(cascade = { CascadeType.PERSIST, CascadeType.REMOVE })
    private Set<Projet> projets;
    
  2. « Dans Equipe, on a mis @ManyToOne(cascade = CascadeType.ALL) Entreprise entreprise;. Supprimer une équipe obsolète est donc sans risque. »

  3. « Pour la bidirectionnelle Entreprise / Equipe, je mets mappedBy sur le @ManyToOne de Equipe. »

  4. « Comme la relation Equipe vers Projet est unidirectionnelle, il est impossible en SQL de retrouver les équipes d’un projet. »

  5. « Une ManyToMany bidirectionnelle crée deux tables de jointure, equipe_projets et projet_equipes, une par sens. »

Lis le code

Relie le code aux concepts.

  1. Quelles tables et quelles colonnes de liaison ce code génère-t-il ?

    @Entity
    public class Entreprise {
        @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long idEntreprise;
        @OneToMany(cascade = CascadeType.ALL)
        private Set<Equipe> equipes;
    }
    
    @Entity
    public class Equipe {
        @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long idEquipe;
    }
    
  2. On modifie l’exemple précédent : Equipe gagne @ManyToOne Entreprise entreprise; et la collection devient @OneToMany(cascade = CascadeType.ALL, mappedBy = "entreprise"). Qu’est-ce qui change en base ?

  3. Avec ce mapping, que se passe-t-il en base quand on (1) sauvegarde une équipe neuve qui contient deux projets neufs, (2) met à jour le nom d’un de ces projets via l’équipe, (3) supprime l’équipe ?

    @ManyToMany(cascade = { CascadeType.PERSIST, CascadeType.REMOVE })
    private Set<Projet> projets;
    
  4. Écris de mémoire la ManyToMany bidirectionnelle entre Equipe (côté propriétaire) et Projet : les deux attributs d’association avec leurs annotations.

Vrai ou faux, justifie

La justification compte plus que le verdict.

  1. « Sans attribut cascade, sauvegarder une Entreprise sauvegarde aussi les nouvelles équipes de sa collection. »

  2. « OneToMany bidirectionnelle et ManyToOne bidirectionnelle désignent la même association. »

  3. « LAZY est toujours le meilleur choix, puisqu’il améliore les performances. »

  4. « orphanRemoval ne sert à rien si on a déjà CascadeType.ALL. »

Classe

Range chaque élément et explique les cas limites.

  1. Pour chaque besoin, donne le CascadeType minimal : (a) sauvegarder les adresses neuves d’un client avec lui ; (b) annuler les modifications locales en relisant la base ; (c) propager une modification d’un objet détaché ; (d) retirer les entités associées du contexte de persistance ; (e) supprimer les lignes de commande avec la commande.

  2. Classe ces associations selon le FetchType que tu choisirais, et dis si c’est déjà le défaut : Equipe.entreprise (toujours affichée avec l’équipe) ; Entreprise.equipes (centaines d’équipes, rarement affichées) ; Projet.projetDetail (affiché seulement sur la page de détail) ; Equipe.projets (affichés seulement à la demande).

Et si...

Prévois la conséquence.

  1. Et si on charge une entreprise (équipes en LAZY), puis qu’on appelle entreprise.getEquipes() ? Que se passe-t-il, et à quel moment ?

  2. Et si, dans la bidirectionnelle Entreprise / Equipe, on oublie mappedBy sur la @OneToMany en gardant le @ManyToOne côté Equipe ?

  3. Et si on passe en EAGER toutes les associations d’Entreprise puis de Equipe, et qu’on liste toutes les entreprises ?