eadl:bloc3:dev_av:td2

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentes Révision précédente
Prochaine révision
Révision précédente
eadl:bloc3:dev_av:td2 [2025/10/07 23:35] jcheroneadl:bloc3:dev_av:td2 [2025/10/08 00:18] (Version actuelle) – [4.4 Optimisation des identifiants avec Tsid] jcheron
Ligne 124: Ligne 124:
 GET /products?type=PHYSICAL GET /products?type=PHYSICAL
 GET /products?type=DIGITAL GET /products?type=DIGITAL
 +</sxh>
 +
 +===== Partie 4 : Hypersistence Utils - Outils avancés (30min-1h) =====
 +
 +==== 4.1 Introduction à Hypersistence Utils ====
 +
 +<WRAP round bloc info>
 +**Hypersistence Utils** est une bibliothèque créée par Vlad Mihalcea qui apporte :
 +  * Des types personnalisés (JSON, Array, etc.)
 +  * Des utilitaires de diagnostic de performance
 +  * Des listeners pour optimiser les opérations
 +  * Des identifiants optimisés (Tsid)
 +</WRAP>
 +
 +=== Dépendance Maven ===
 +
 +<sxh xml;gutter:false>
 +<dependency>
 +    <groupId>io.hypersistence</groupId>
 +    <artifactId>hypersistence-utils-hibernate-63</artifactId>
 +    <version>3.7.0</version>
 +</dependency>
 +</sxh>
 +
 +==== 4.2 Détection automatique des problèmes N+1 ====
 +
 +<WRAP round bloc important>
 +**Objectif :** Détecter automatiquement les problèmes de performance sans analyse manuelle des logs
 +</WRAP>
 +
 +=== Configuration ===
 +
 +<sxh bash;gutter:false>
 +# application.properties - Ajout pour Hypersistence
 +
 +# Détection des problèmes N+1
 +logging.level.io.hypersistence.utils=DEBUG
 +
 +# Limites d'alerte (optionnel)
 +hypersistence.query.fail.on.pagination.over.collection.fetch=false
 +</sxh>
 +
 +=== Utilisation du QueryStackTraceLogger ===
 +
 +<sxh java;gutter:false>
 +// Configuration globale (classe @Configuration)
 +@Configuration
 +public class HypersistenceConfiguration {
 +    
 +    @Bean
 +    public QueryStackTraceLogger queryStackTraceLogger() {
 +        return new QueryStackTraceLogger();
 +    }
 +    
 +    @EventListener
 +    public void onApplicationEvent(ApplicationReadyEvent event) {
 +        // Active la détection des problèmes N+1
 +        QueryStackTraceLogger.INSTANCE.setThreshold(10); // Alerte si > 10 requêtes
 +    }
 +}
 +</sxh>
 +
 +**Exercice :** 
 +  * Activer le logger sur l'endpoint ''/users/{id}/orders''
 +  * Observer les alertes automatiques
 +  * Corriger les problèmes détectés
 +
 +==== 4.3 Types JSON natifs ====
 +
 +<WRAP round bloc todo>
 +**Cas d'usage :** Stocker des métadonnées flexibles sur les produits
 +</WRAP>
 +
 +=== Exemple : Attributs dynamiques produit ===
 +
 +<sxh java;gutter:false>
 +@Entity
 +@Table(name = "products")
 +public class Product {
 +    // ... attributs existants
 +    
 +    @Type(JsonType.class)
 +    @Column(columnDefinition = "json")
 +    private Map<String, Object> attributes;
 +    
 +    // Pour PhysicalProduct : {"weight": 2.5, "dimensions": "30x20x10"}
 +    // Pour DigitalProduct : {"fileSize": "1.2GB", "format": "PDF"}
 +}
 +</sxh>
 +
 +=== Données exemple ===
 +
 +<sxh json;gutter:false>
 +{
 +  "id": "550e8400-e29b-41d4-a716-446655440020",
 +  "name": "iPhone 15 Pro",
 +  "price": 1199.99,
 +  "stock": 25,
 +  "categoryId": "550e8400-e29b-41d4-a716-446655440010",
 +  "attributes": {
 +    "color": "Titanium Blue",
 +    "storage": "256GB",
 +    "warranty": "2 years"
 +  }
 +}
 +</sxh>
 +
 +**Exercice :**
 +  * Ajouter le champ ''attributes'' à ''Product''
 +  * Créer un endpoint ''GET /products/{id}/attributes''
 +  * Filtrer les produits par attribut : ''GET /products?attr.color=Blue''
 +
 +==== 4.4 Optimisation des identifiants avec Tsid ====
 +
 +<WRAP round bloc info>
 +**Tsid (Time-Sorted Identifiers)** :
 +  * Alternative performante aux UUID
 +  * Triables chronologiquement
 +  * Plus compacts (Long au lieu de UUID)
 +  * Meilleure performance en base
 +</WRAP>
 +
 +=== Comparaison UUID vs Tsid ===
 +
 +<sxh java;gutter:false>
 +// Avant (UUID)
 +@Id
 +@GeneratedValue(strategy = GenerationType.UUID)
 +private UUID id;
 +
 +// Après (Tsid) - Pour nouvelles entités
 +@Id
 +@TsidGenerator
 +private Long id;
 +</sxh>
 +
 +**Exercice optionnel :**
 +  * Créer une nouvelle entité ''Review'' avec Tsid
 +  * Comparer les performances d'insertion (benchmark)
 +
 +<html><div class="imageB"></html>
 +<uml>
 +@startuml Review Domain Model
 +
 +class Review {
 +  - id : Long
 +  - rating : Integer
 +  - title : String
 +  - comment : String
 +  - verified : Boolean
 +  - helpfulCount : Integer
 +  - createdAt : LocalDateTime
 +  - updatedAt : LocalDateTime
 +}
 +
 +class Product {
 +  - id : UUID
 +  - name : String
 +  - price : BigDecimal
 +  - stock : Integer
 +}
 +
 +class User {
 +  - id : UUID
 +  - username : String
 +  - email : String
 +}
 +
 +Product "1" -- "0..*" Review : product
 +User "1" -- "0..*" Review : author
 +
 +note right of Review
 +  Contraintes métier :
 +  • rating ∈ [1..5]
 +  • 1 review max par (user, product)
 +  • verified = true si achat confirmé
 +  • helpfulCount >= 0
 +  
 +  Tsid Generator pour l'id
 +  (performance + tri chronologique)
 +end note
 +
 +@enduml
 +
 +
 +
 +</uml>
 +<html></div></html>
 +
 +==== 4.5 Monitoring des requêtes en temps réel ====
 +
 +=== DataSourceProxyBeanPostProcessor ===
 +
 +<sxh java;gutter:false>
 +@Configuration
 +public class DataSourceProxyConfiguration {
 +    
 +    @Bean
 +    public DataSourceProxyBeanPostProcessor dataSourceProxyBeanPostProcessor() {
 +        return new DataSourceProxyBeanPostProcessor() {
 +            @Override
 +            protected DataSourceProxy createDataSourceProxy(DataSource dataSource) {
 +                return new DataSourceProxy(dataSource, new QueryCountHolder());
 +            }
 +        };
 +    }
 +}
 +</sxh>
 +
 +**Exercice :**
 +  * Mettre en place le monitoring
 +  * Créer un test d'intégration qui vérifie le nombre exact de requêtes
 +  * Exemple : ''assertQueryCount(3)'' après un appel API
 +
 +==== 4.6 Exercice intégratif ====
 +
 +<WRAP round bloc todo>
 +**Mission :** Améliorer l'endpoint recommendations
 +
 +<sxh;gutter:false>
 +GET /users/{id}/recommendations
 +</sxh>
 +
 +**Avec Hypersistence :**
 +  * Détecter automatiquement les problèmes N+1
 +  * Limiter à 5 requêtes maximum (assertion en test)
 +  * Stocker les préférences utilisateur en JSON
 +  * Logger les performances de la recommandation
 +
 +**Structure JSON recommandée :**
 +<sxh json;gutter:false>
 +// User.preferences (JSON)
 +{
 +  "priceRange": {"min": 50, "max": 500},
 +  "brands": ["Apple", "Samsung"],
 +  "excludeCategories": ["550e8400-..."]
 +}
 +</sxh>
 +</WRAP>
 +
 +===== Configuration complète =====
 +
 +<sxh bash;gutter:false>
 +# application.properties - Configuration complète Séance 2
 +
 +# H2 Database
 +spring.datasource.url=jdbc:h2:file:./data/ecommerce
 +spring.datasource.driverClassName=org.h2.Driver
 +spring.datasource.username=sa
 +spring.datasource.password=
 +
 +# H2 Console
 +spring.h2.console.enabled=true
 +spring.h2.console.path=/h2-console
 +
 +# JPA/Hibernate
 +spring.jpa.hibernate.ddl-auto=update
 +spring.jpa.show-sql=true
 +spring.jpa.properties.hibernate.format_sql=true
 +spring.jpa.properties.hibernate.use_sql_comments=true
 +spring.jpa.properties.hibernate.generate_statistics=true
 +
 +# Logging SQL et statistiques
 +logging.level.org.hibernate.SQL=DEBUG
 +logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
 +logging.level.org.hibernate.stat=DEBUG
 +logging.level.org.hibernate.orm.jdbc.bind=TRACE
 +
 +# Hypersistence Utils
 +logging.level.io.hypersistence.utils=DEBUG
 </sxh> </sxh>
  
Ligne 135: Ligne 405:
   * ✅ Résolution problème N+1 sur au moins 2 endpoints   * ✅ Résolution problème N+1 sur au moins 2 endpoints
   * ✅ Implémentation héritage produits (1 stratégie au choix)   * ✅ Implémentation héritage produits (1 stratégie au choix)
 +  * ✅ **Hypersistence : détection automatique N+1 activée**
   * ✅ Tests d'intégration validant les performances   * ✅ Tests d'intégration validant les performances
  
 **Nice to have :** **Nice to have :**
   * Comparaison des 3 stratégies d'héritage   * Comparaison des 3 stratégies d'héritage
-  * DTO Projections avec MapStruct +  * **Type JSON pour attributs dynamiques produits** 
-  * Benchmark avant/après optimisations+  * **Tsid sur une nouvelle entité (Review, Wishlist...)** 
 +  * Benchmark avant/après optimisations avec query count assertions
   * Documentation des choix architecturaux   * Documentation des choix architecturaux
 </WRAP> </WRAP>
- 
-===== Critères d'évaluation ===== 
- 
-^ Critère ^ Points ^ 
-| Associations correctement mappées | 25% | 
-| Résolution problèmes N+1 | 30% | 
-| Implémentation héritage | 25% | 
-| Tests et qualité code | 20% | 
- 
-===== Configuration supplémentaire ===== 
- 
-<sxh yaml;gutter:false> 
-# application.yml - pour la séance 
-spring: 
-  jpa: 
-    show-sql: true 
-    properties: 
-      hibernate: 
-        format_sql: true 
-        use_sql_comments: true 
-        generate_statistics: true # Pour mesurer les perfs 
-logging: 
-  level: 
-    org.hibernate.stat: DEBUG # Statistiques Hibernate 
-</sxh> 
  
 ===== Ressources ===== ===== Ressources =====
  
   * [[https://vladmihalcea.com/tutorials/hibernate/|Hibernate Performance Best Practices]]   * [[https://vladmihalcea.com/tutorials/hibernate/|Hibernate Performance Best Practices]]
 +  * [[https://github.com/vladmihalcea/hypersistence-utils|Hypersistence Utils GitHub]]
 +  * [[https://hypersistence.io/|Documentation officielle Hypersistence]]
   * [[https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods|Spring Data JPA Query Methods]]   * [[https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods|Spring Data JPA Query Methods]]
 +
  
 <WRAP round bloc info> <WRAP round bloc info>
  • eadl/bloc3/dev_av/td2.1759872946.txt.gz
  • Dernière modification : il y a 23 heures
  • de jcheron