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.
Sans regarder : empile la stack de persistance de l’application jusqu’à la base, et donne pour chaque couche la classe ou l’interface qui la représente.
Couche Représentant Rôle Application User.java,UserRepository.javaEntités et repositories du métier Spring Data JPA CrudRepository,JpaRepositorySimplifie l’accès aux données JPA jakarta.persistence.EntityManagerSpécification : une interface Hibernate org.hibernate.SessionImplémentation concrète de JPA JDBC javax.sql.PreparedStatementAPI bas niveau, connexion directe Base relationnelle Moyen mnémotechnique : on descend du plus abstrait (Spring Data) au plus concret (JDBC), avec la spécification (JPA) au-dessus de son implémentation (Hibernate).
Donne les phases du cycle de vie Maven avec leur commande, et pour chacune ce qu’elle produit ou modifie sur le disque.
Commande Effet mvn compile.javavers.classmvn testexécute les tests unitaires mvn packagegénère le livrable dans /targetmvn installcopie le livrable dans le repo local ~/.m2mvn deployenvoie le livrable vers le repo distant mvn cleansupprime /targetLe fil conducteur : le livrable va de
/target(package), à~/.m2(install), puis au dépôt distant (deploy).Cite les quatre starters du projet AutoLoc et ce que le projet perdrait si on retirait chacun d’eux.
- Spring Data JPA : plus de persistance ni de mapping objet-relationnel avec MySQL.
- MySQL Driver : plus de connexion entre Spring Boot et MySQL.
- Lombok : il faudrait réécrire getters, setters, constructeurs… à la main.
- Spring Web : plus d’API REST ni d’endpoints exposés.
Cite les annotations JPA vues en cours et classe-les : obligatoires pour qu’une entité existe, ou optionnelles. Que fait chacune des optionnelles si on l’omet ?
- Obligatoires :
@Entity(classe persistante associée à une table) et@Id(clé primaire). - Optionnelles :
@Table(name=...): omise, la table prend le nom de la classe.@Column(name=...): omise, la colonne garde le nom de l’attribut.@GeneratedValue(strategy=...): omise, la clé n’est pas générée, c’est à toi de la fournir.@Enumerated(EnumType.STRING): pour un attribut Enum, stocke la valeur enString.
- Obligatoires :
Distingue
Deux notions proches : dis ce qui les sépare vraiment.
JPA et Hibernate : un camarade dit « c’est la même chose ». Corrige-le en une phrase, puis donne l’interface qui représente chacun.
JPA est une spécification (une norme, un ensemble d’interfaces), Hibernate est un produit qui implémente cette spécification.
JPA :
jakarta.persistence.EntityManager. Hibernate :org.hibernate.Session. D’autres fournisseurs implémentent JPA (EclipseLink, Toplink), c’est tout l’intérêt d’une spécification.Hibernate génère déjà le SQL du CRUD. Qu’apporte Spring Data JPA en plus, et sur quoi repose-t-il ?
Hibernate fait le mapping et génère le SQL et les tables, mais il faut encore écrire le code qui l’utilise. Spring Data JPA fournit des interfaces prêtes à l’emploi (
CrudRepository,JpaRepository,PagingAndSortingRepository) : on déclare une interface qui les étend, et les requêtes basiques existent sans en écrire une ligne.Il repose sur Hibernate comme implémentation de JPA, il ne le remplace pas. Spring Data offre aussi une abstraction commune quelle que soit la source (SQL ou NoSQL).
Repository local, distant, interne : où se trouve chacun, dans quel ordre Maven les consulte, et pourquoi une entreprise voudrait le troisième ?
- Local :
~/.m2/repository, le cache sur ta machine. Consulté en premier. - Distant : Maven Central (via mvnrepository.com), contacté seulement si la dépendance n’est pas en local.
- Interne (privé) : un dépôt distant hébergé sur les serveurs de l’entreprise, pour des raisons de sécurité.
Tous sont organisés en groupes, artefacts et versions.
- Local :
IDENTITY,AUTO,SEQUENCE,TABLE: qui produit l’identifiant dans chaque cas ?Stratégie Qui génère l’id IDENTITYLe SGBD lui-même ( AUTO_INCREMENT), Hibernate s’appuie dessusAUTOHibernate (séquence globale) SEQUENCEUne séquence définie manuellement TABLEUne table dédiée aux séquences Mode standalone et mode plugin de Maven : où sert chacun ?
Le mode plugin est intégré par défaut dans IntelliJ IDEA, pour le développeur. Le mode standalone est installé seul sur une machine et sert en CI/CD, là où aucun IDE ne tourne : c’est lui qui automatise build, tests et livrables dans la chaîne DevOps.
Explique pourquoi
Le mécanisme derrière la règle.
Quel problème l’ORM résout-il ? Explique-le avec les deux modèles en jeu, puis cite trois limites de JDBC qui justifient de ne pas tout écrire à la main.
Le modèle relationnel (tables, SGBDR) et le modèle objet (classes Java) ne communiquent pas nativement : il faut projeter les objets en mémoire vers des tables. L’ORM associe une classe à une table et chaque attribut à une colonne, et réduit le code à écrire.
Limites de JDBC : pas de séparation entre code technique et code métier, SQL qui rend la couche d’accès difficile à maintenir, code verbeux et répétitif.
Avec Spring Boot, on ajoute un starter sans jamais préciser la version de ses dizaines de dépendances, et pourtant tout est compatible. Pourquoi ?
Un starter ramène toutes les dépendances nécessaires en une seule déclaration, et le parent
spring-boot-starter-parentgère automatiquement les versions compatibles entre elles. Le développeur se concentre sur le métier, pas sur la résolution des conflits de versions.Que veut dire « convention over configuration » pour Maven, et en quoi est-ce un avantage face à Gradle ou Ant ?
L’arborescence est prédéfinie : le code dans
/src/main/java, les tests dans/src/test/java, les ressources dans/src/main/resources, les résultats dans/target. Il n’y a rien à configurer pour que Maven trouve les fichiers. Chez Gradle ou Ant, une configuration supplémentaire est requise. Bonus : n’importe quel développeur s’y retrouve dans n’importe quel projet Maven.Pourquoi le cours lie-t-il Maven à l’intégration continue (DevOps) ?
Maven automatise les tâches récurrentes : compilation, gestion des dépendances, lancement des tests, génération des livrables. Une chaîne CI n’a qu’à lancer les phases du cycle de vie (en mode standalone) pour reproduire le même build à chaque commit.
Pourquoi annoter un attribut Enum avec
@Enumerated(EnumType.STRING)plutôt que laisser le comportement par défaut ?Avec
STRING, la base stocke le nom de la valeur (DISPONIBLE,EN_LIVRAISON) : la table reste lisible et la donnée ne dépend pas de l’ordre des constantes dans l’enum.Au-delà du cours : sans cette annotation, JPA stocke par défaut l’ordinal (0, 1, 2…). Réordonner ou insérer une constante dans l’enum changerait alors silencieusement le sens des lignes déjà en base.
Cas pratique
Choisis et justifie avec les critères du cours.
Ton entreprise interdit aux serveurs de build d’accéder à Internet, donc à Maven Central. Comment le projet obtient-il ses dépendances ?
Par un dépôt distant interne (privé), hébergé sur les serveurs de l’entreprise : c’est exactement le cas prévu « pour des raisons de sécurité ». Maven consulte d’abord le repo local
~/.m2, puis ce dépôt interne à la place de Maven Central.Le client veut déployer AutoLoc sur un Tomcat déjà installé dans son SI, pas en lançant un jar. Spring Boot le permet-il ? Que change-t-on ?
Oui. Par défaut Spring Boot embarque son serveur (le jar de Tomcat se dézippe et se lance), mais le packaging
.warreste possible justement pour la compatibilité avec des serveurs existants. On produit un.warau lieu d’un jar exécutable.On veut passer AutoLoc de MySQL à PostgreSQL. Quels éléments du projet changent, et pourquoi les entités
LivreuretPaiementne changent-elles pas ?Changent : le driver (starter MySQL Driver remplacé par celui de PostgreSQL) et la datasource dans
application.properties(spring.datasource.url, identifiants).Les entités ne bougent pas parce qu’elles ne parlent qu’à JPA, une spécification indépendante du SGBD. C’est Hibernate qui génère le SQL adapté à la base. Le code reste écrit contre la norme, pas contre MySQL.
Tu lances l’application, aucune erreur, mais la table
paiementn’apparaît pas dansautoloc_db. Liste trois choses à vérifier, dans l’ordre où tu le ferais.- La classe porte bien
@Entity(et un@Id), sinon elle n’est pas persistante. spring.jpa.hibernate.ddl-auto=updateest présent : c’est lui qui fait générer les tables.spring.datasource.urlpointe bien vers la bonne base (?createDatabaseIfNotExist=truecrée la base si elle manque). Avecspring.jpa.show-sql=true, la console montre le SQL généré, donc si lecreate tableapparaît ou non.
- La classe porte bien
Trouve l'erreur
Chaque affirmation contient au moins une faute.
« Hibernate est la spécification Jakarta EE de la persistance, et JPA est son implémentation la plus connue. »
C’est l’inverse : JPA est la spécification (Jakarta Persistence API), Hibernate en est une implémentation, maintenue par JBoss / RedHat.
« Pour repartir de zéro, je lance
mvn clean: il vide~/.m2et force le retéléchargement des dépendances. »mvn cleansupprime seulement le dossier/target(les fichiers résultat du build). Le repo local~/.m2n’est pas touché, les dépendances restent en cache.« Depuis qu’on utilise Spring Data JPA, on a retiré Hibernate du projet, il ne sert plus. »
Spring Data JPA se base sur Hibernate comme implémentation de JPA. Il simplifie l’accès aux données au-dessus de la stack, il ne remplace aucune des couches en dessous (JPA, Hibernate, JDBC).
Trouve ce qui empêche cette classe d’être une entité valide :
@Entity @Table(name = "paiement") public class Paiement { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long idPaiement; private Double montant; private ModePaiement mode; }Il manque
@Id: une entité doit avoir au moins une propriété déclarée comme identité.@GeneratedValueseul ne fait pas deidPaiementune clé primaire.Amélioration :
modeest une Enum, l’annoter@Enumerated(EnumType.STRING)pour stocker le nom de la valeur.« Lombok est le module ORM de Spring : il génère les getters, setters et les tables de la base. »
Lombok est une bibliothèque Java qui remplace le code répétitif (getters, setters, constructeurs,
equals,hashCode,toString) par des annotations. Il n’a rien à voir avec la persistance : ce sont Hibernate / JPA qui génèrent les tables.« J’ai mis
LivreurServiceTest.javadans/src/main/java, à côté du service qu’il teste, c’est plus pratique. »Par convention Maven, le code de test va dans
/src/test/java(et ses ressources dans/src/test/resources). Placé dans/src/main/java, il serait compilé et embarqué dans le livrable comme du code de production.
Lis le code
Relie le code aux concepts.
À partir de cette entité, décris la table créée : son nom, ses colonnes, la façon dont la clé est produite, et ce qui est stocké dans
statut.@Entity @Table(name = "livreur") @Getter @Setter @NoArgsConstructor @AllArgsConstructor public class Livreur { @Id @GeneratedValue(strategy = IDENTITY) private Long idLivreur; private String nom; private String prenom; private String telephone; @Enumerated(EnumType.STRING) private StatutLivreur statut; }- Table
livreur(nom imposé par@Table). - Colonnes :
id_livreur(clé primaire),nom,prenom,telephone,statut. - Clé :
IDENTITY, doncAUTO_INCREMENTgéré par MySQL. statut: le nom de la valeur de l’enum, en texte.
Les annotations Lombok ne touchent pas à la table : elles génèrent getters, setters et les deux constructeurs.
- Table
Dans ce code, où se trouve le SQL ? Quel rôle joue
@AllArgsConstructorsur le service ? À quelle couche appartient chaque type ?public interface ProjetDetailRepository extends JpaRepository<ProjetDetail, Long> { } @Service @AllArgsConstructor public class ProjetDetailService { private ProjetDetailRepository projetDetailRepository; public void addEtudiant(ProjetDetail projetDetail) { projetDetailRepository.save(projetDetail); } }- Pas de SQL écrit :
savevient deJpaRepository, Spring Data JPA fournit l’implémentation et Hibernate génère l’INSERT. @AllArgsConstructorgénère un constructeur qui prend le repository : Spring l’utilise pour injecter leProjetDetailRepositorydans le service.- Couches : le repository est la persistance, le service (
@Service) porte la logique métier et consomme le repository. JpaRepository<ProjetDetail, Long>: l’entité gérée et le type de sa clé.
- Pas de SQL écrit :
Explique l’effet de chacune de ces lignes au démarrage de l’application.
spring.datasource.url=jdbc:mysql://localhost:3306/ProjetSpring?createDatabaseIfNotExist=true spring.jpa.show-sql=true spring.jpa.hibernate.ddl-auto=updatedatasource.url: connexion JDBC à MySQL surlocalhost:3306, baseProjetSpring, créée si elle n’existe pas.show-sql=true: chaque requête SQL générée par Hibernate s’affiche en console.ddl-auto=update: Hibernate génère et met à jour les tables à partir des entités au démarrage.
Vrai ou faux, justifie
La justification compte plus que le verdict.
« Pour faire tourner une application Spring Boot, il faut d’abord installer un serveur Tomcat sur la machine. »
Faux. Spring Boot fournit un serveur HTTP embarqué (Tomcat, Jetty…) : au lancement, le jar de Tomcat se dézippe et se lance. Aucun serveur externe n’est requis, le
.warn’existe que pour les serveurs déjà en place.« Maven télécharge les dépendances depuis Maven Central à chaque build. »
Faux. Maven vérifie d’abord le repo local
~/.m2/repositoryet ne contacte le distant que pour ce qui manque. Les dépendances déjà téléchargées sont en cache.« Avec un ORM, on n’a plus de connexion, de CRUD ni de déconnexion à faire. »
Faux. Les opérations restent les mêmes (connexion, CRUD, déconnexion). L’ORM réduit la quantité de code à écrire pour les faire, il ne les supprime pas.
« Spring Data est lié aux bases relationnelles. »
Faux. Spring Data offre une abstraction commune pour l’accès aux données quelle que soit la source, SQL ou NoSQL. C’est son sous-projet Spring Data JPA qui cible le relationnel via JPA.
Classe
Range chaque élément et explique les cas limites.
Range chaque fichier à sa place dans l’arborescence Maven :
Livreur.java,LivreurServiceTest.java,application.properties,logo.png,autoloc-0.0.1.jar(généré), le fichier de config utilisé seulement par les tests.Fichier Emplacement Livreur.java/src/main/javaLivreurServiceTest.java/src/test/javaapplication.properties/src/main/resourceslogo.png/src/main/resourcesautoloc-0.0.1.jar/targetconfig des tests /src/test/resourcesRange chaque élément : spécification, implémentation ORM, abstraction Spring, ou API bas niveau. JPA, Hibernate, EclipseLink, Spring Data JPA, JDBC,
EntityManager,Session,PreparedStatement,JpaRepository.- Spécification : JPA,
EntityManager. - Implémentation ORM : Hibernate, EclipseLink,
Session. - Abstraction Spring : Spring Data JPA,
JpaRepository. - API bas niveau : JDBC,
PreparedStatement.
- Spécification : JPA,
Et si...
Prévois la conséquence.
Et si tu lances directement
mvn installalors qu’un test unitaire échoue ? Qu’est-ce qui arrive dans~/.m2?Les phases s’exécutent dans l’ordre : compile, test, package, puis install. Le test qui échoue arrête le cycle à la phase
test: aucun livrable n’est produit, et rien n’est copié dans~/.m2.Et si on ajoute un attribut
emailà l’entitéLivreuret qu’on relance l’application avecddl-auto=update?Hibernate met à jour la table au démarrage : la colonne
emailest ajoutée àlivreur, sans recréer la table ni perdre les lignes existantes. Avecshow-sql=true, la requête qui modifie la table apparaît en console.Et si on supprime
@GeneratedValuedeidLivreurmais qu’on garde@Id?L’entité reste valide (
@Idest la seule annotation obligatoire sur la clé), mais plus rien ne génère l’identifiant : c’est au code de fournir la valeur avant chaque sauvegarde. Sans valeur, l’enregistrement d’un nouveau livreur échoue.