Hibernate ORM et Jakarta Persistence
Problème → anti-pattern → bibliothèque de correction pour le mapping d'entités et les requêtes. Framework-neutre : couvre le comportement EntityManager/Session, JPQL/HQL et les annotations de mapping. Si le projet utilise Spring Boot et les skills java-springboot et spring-boot-testing sont installés, utilisez-les pour les repositories Spring Data, le wiring des transactions et @DataJpaTest ; pour Panache et la persistance réactive, voir les skills Quarkus. Tests d'intégration contre une vraie base de données : java-testcontainers.
D'abord : détecter la stack
- Lire
pom.xml/build.gradle(ou l'arborescence des dépendances) pourhibernate-coreet l'API de persistance :jakarta.persistence(Hibernate 6+/Jakarta EE 9+) vsjavax.persistence(Hibernate 5, voirjavax-to-jakarta-migration). - Noter la version majeure d'Hibernate ; le comportement diffère (voir
references/tooling-and-versions.md). Hibernate 6.0-6.1 implémente Jakarta Persistence 3.0, 6.2+ implémente 3.1, 7.x implémente 3.2, et Hibernate 7 nécessite Java 17+. - Noter la base de données et si le schéma est géré par Flyway/Liquibase.
- Activer la journalisation SQL et les statistiques dans un test (voir
references/tooling-and-versions.md) avant d'« optimiser » quoi que ce soit : mesurer les comptes d'instructions.
Tableau décisionnel rapide
| Symptôme | Cause probable | Aller à |
|---|---|---|
| Beaucoup de SELECTs similaires pour une requête | N+1 sur association lazy | references/fetching-and-n-plus-one.md |
LazyInitializationException |
Accès lazy en dehors de la session | references/fetching-and-n-plus-one.md |
Avertissement HHH000104 / HHH90003004, grosse utilisation mémoire |
Pagination avec collection fetch join | references/queries-pagination-batching.md |
| Inserts lents, pas de batching JDBC | IDs IDENTITY ou batching non configuré |
references/identifiers-and-entity-design.md, references/queries-pagination-batching.md |
Lignes dupliquées / enfants perdus / anomalies Set |
Mauvais equals/hashCode ou misuse de cascade |
references/identifiers-and-entity-design.md, references/associations-and-cascade.md |
| Mises à jour perdues, deadlocks | Stratégie de locking manquante | references/locking-transactions-caching.md |
| Données obsolètes ou surprenantes avec caches | Misuse du cache de second niveau/requête | references/locking-transactions-caching.md |
Dérive de schéma, ddl-auto en prod |
Pas d'outil de migration | references/tooling-and-versions.md |
Règles principales (appliquer lors de la review)
- Associations :
@ManyToOne/@OneToOnedéfaut à EAGER ; déclarer explicitementfetch = FetchType.LAZY.@OneToMany/@ManyToManysont LAZY par défaut et doivent le rester. Choisir le fetching par requête (JOIN FETCH, entity graph), pas en rendant les mappings EAGER. - Préférer
@ManyToOnecôté owning plus une@OneToMany(mappedBy=...)bidirectionnelle seulement si nécessaire ; garder les deux côtés en sync via des méthodes helper. SetouListpour les collections ? UtiliserSetpour@ManyToMany; une@OneToManyunidirectionnelle avec@JoinColumnouListsans order a des patterns de mise à jour coûteux.- Ne jamais utiliser
CascadeType.REMOVE/ALLsur@ManyToOneou@ManyToMany. UtiliserorphanRemovalseulement sur une vraie collection d'enfants parent-owned. - Ids :
SEQUENCE(pooled optimizer,allocationSizecorrespondant à l'incrément DB) pour les ids numériques générés ;IDENTITYdésactive le batching d'insert JDBC ; utiliser des UUIDs (préférablement time-ordered) quand les ids doivent être générés côté client. - Entités : pas de Lombok
@Data/@EqualsAndHashCode/@ToStringsur les associations ; implémenterequals/hashCodedélibérément. - Retourner des DTOs/projections depuis les endpoints de lecture plutôt que des entités ; ne jamais exposer directement les entités (proxies lazy) dans une API.
- Paginer avec un
ORDER BYstable incluant un unique tiebreaker ; ne jamais combinersetMaxResultsavec un collectionJOIN FETCH. - Garder les transactions courtes, à la limite du service ; pas d'appels distants ou d'interaction utilisateur dedans.
- Écrire et flusher par batches pour le travail en masse et vider régulièrement le contexte de persistance.
- Vérifier le comportement avec les comptes d'instructions dans les tests contre le moteur de base de données réel.
- Suivre la règle de gestion de schéma ci-dessous.
Règle de gestion de schéma
C'est l'unique règle que les autres skills référencent par nom :
- Prototype/local :
hibernate.hbm2ddl.auto=update(oucreate-droppour les tests jetables) est acceptable. - Production (défaut) : migrations versionnées avec Flyway ou Liquibase, et
hibernate.hbm2ddl.auto=validate(ounone). Les ajouter quand l'utilisateur veut des migrations versionnées ou l'app est destinée à la production. - Schéma géré externalement :
none(ouvalidate) ; ne pas ajouter d'outil de migration.
Focus de review
Vérifier les comptes d'instructions pour N+1, LAZY explicite sur les associations to-one, ids basés sur sequence avec allocationSize correspondant, et equals/hashCode stable de transient à persistent. Détails dépendant de la version (Hibernate 5/6/7) : references/tooling-and-versions.md.
Références
references/fetching-and-n-plus-one.md: détection et corrections N+1, lazy vs eager,LazyInitializationException, open-session-in-view, projections DTO.references/identifiers-and-entity-design.md: génération d'id,equals/hashCode, Lombok, records vs entités, enums et converters, value types.references/associations-and-cascade.md: helpers bidirectionnels, cascade,orphanRemoval, choix de collection,@ManyToMany.references/queries-pagination-batching.md: pagination (offset, keyset, avertissement en-mémoire), opérations en masse, batching JDBC,StatelessSession.references/locking-transactions-caching.md: locking optimiste/pessimiste, limites de transaction, flush modes, cache de second niveau.references/tooling-and-versions.md: journalisation SQL, statistiques, tests, dimensionnement du pool de connexions, migrations, différences Hibernate 5/6/7.
Docs canoniques : guide utilisateur Hibernate ORM https://docs.hibernate.org/orm/current/userguide/html_single/ et Jakarta Persistence https://jakarta.ee/specifications/persistence/. Articles de fond : https://vladmihalcea.com/.
Upgrading (récupérer la page pour la version cible ; la préférer à ce skill) : guides de migration https://hibernate.org/orm/documentation/migrate/ (6.6 : https://docs.hibernate.org/orm/6.6/migration-guide/, 7.0 : https://docs.hibernate.org/orm/7.0/migration-guide/), notes de release https://hibernate.org/orm/releases/.