Aller au contenu principal

Chapitre 1: Conventions de Nommage Avancées

Introduction​

Dans le Module 2, vous avez appris 3 mots-clés simples: findBy, And, Or.

Maintenant, vous allez apprendre 15+ mots-clés supplémentaires pour créer des requêtes complexes!

Ce que vous allez apprendre​

  1. Les 15+ mots-clés de Spring Data JPA
  2. Comment les combiner
  3. Des exemples pour chaque mot-clé

Durée: 1h


Comment Ça Marche?​

Principe Magique de Spring Data JPA​

public interface ProductRepository extends JpaRepository<Product, Long> {

List<Product> findByPriceLessThan(Double maxPrice);
// ^^^^^^ ^^^^^ ^^^^^^^
// find By PriceLessThan
}

Spring lit le nom de la méthode et génère le SQL automatiquement!

-- SQL généré automatiquement:
SELECT * FROM product WHERE price < ?

Vous n'écrivez PAS de SQL, Spring le fait pour vous!


Structure des Noms de Méthodes​

findBy + [Champ] + [Opération] + [AutreChamp] + [Opération]

Exemples:

findByName                    // WHERE name = ?
findByPriceLessThan // WHERE price < ?
findByNameAndPrice // WHERE name = ? AND price = ?
findByPriceBetween // WHERE price BETWEEN ? AND ?

Les 15+ Mots-Clés​

1. And / Or (Vous connaissez déjà)​

Combiner plusieurs conditions:

// AND
List<Product> findByNameAndPrice(String name, Double price);
// SQL: WHERE name = ? AND price = ?

// OR
List<Product> findByNameOrCategory(String name, String category);
// SQL: WHERE name = ? OR category = ?

Exemple concret:

// Trouver un produit "Laptop" à 999.99€
productRepo.findByNameAndPrice("Laptop", 999.99);

2. Between (Entre deux valeurs)​

Trouver des valeurs dans un intervalle:

List<Product> findByPriceBetween(Double min, Double max);
// SQL: WHERE price BETWEEN ? AND ?

Exemple:

// Produits entre 100€ et 500€
List<Product> products = productRepo.findByPriceBetween(100.0, 500.0);

Cas d'usage:

  • Prix dans une fourchette
  • Dates entre deux moments
  • Ages entre min et max

3. LessThan / GreaterThan (Comparaisons)​

Comparer des valeurs numériques ou dates:

// Inférieur à
List<Product> findByPriceLessThan(Double maxPrice);
// SQL: WHERE price < ?

// Inférieur ou égal
List<Product> findByPriceLessThanEqual(Double maxPrice);
// SQL: WHERE price <= ?

// Supérieur à
List<Product> findByPriceGreaterThan(Double minPrice);
// SQL: WHERE price > ?

// Supérieur ou égal
List<Product> findByPriceGreaterThanEqual(Double minPrice);
// SQL: WHERE price >= ?

Exemples:

// Produits à moins de 100€
productRepo.findByPriceLessThan(100.0);

// Produits à 100€ ou moins
productRepo.findByPriceLessThanEqual(100.0);

// Produits à plus de 1000€
productRepo.findByPriceGreaterThan(1000.0);

Cas d'usage:

  • Prix min/max
  • Stock minimum
  • Age minimum/maximum
  • Dates avant/après

4. Like / Containing / StartingWith / EndingWith (Recherche Texte)​

Rechercher dans des chaînes de caractères:

// LIKE (vous fournissez les %)
List<Product> findByNameLike(String pattern);
// SQL: WHERE name LIKE ?
// Utilisation: findByNameLike("%Laptop%")

// CONTAINING (Spring ajoute les % automatiquement)
List<Product> findByNameContaining(String keyword);
// SQL: WHERE name LIKE ?
// Utilisation: findByNameContaining("Laptop")
// Cherche: %Laptop%

// STARTING WITH (cherche au début)
List<Product> findByNameStartingWith(String prefix);
// SQL: WHERE name LIKE ?
// Utilisation: findByNameStartingWith("Mac")
// Cherche: Mac%

// ENDING WITH (cherche à la fin)
List<Product> findByNameEndingWith(String suffix);
// SQL: WHERE name LIKE ?
// Utilisation: findByNameEndingWith("Pro")
// Cherche: %Pro

Exemples:

// Produits contenant "phone" (iPhone, smartphone, etc.)
productRepo.findByNameContaining("phone");

// Produits commençant par "Mac" (MacBook, Mac Mini, etc.)
productRepo.findByNameStartingWith("Mac");

// Produits finissant par "Pro" (MacBook Pro, iPad Pro, etc.)
productRepo.findByNameEndingWith("Pro");

Différence Like vs Containing:

// Like - vous contrôlez les %
findByNameLike("%Laptop%") // Contient Laptop
findByNameLike("Laptop%") // Commence par Laptop
findByNameLike("%Laptop") // Finit par Laptop

// Containing - Spring ajoute les %
findByNameContaining("Laptop") // Contient Laptop (%Laptop%)

5. In / NotIn (Dans une liste)​

Vérifier si une valeur est dans une liste:

// IN
List<Product> findByCategoryIn(List<String> categories);
// SQL: WHERE category IN (?, ?, ?)

// NOT IN
List<Product> findByCategoryNotIn(List<String> categories);
// SQL: WHERE category NOT IN (?, ?, ?)

Exemples:

// Produits dans plusieurs catégories
List<String> categories = Arrays.asList("Electronics", "Computers", "Phones");
productRepo.findByCategoryIn(categories);

// Produits PAS dans ces catégories
productRepo.findByCategoryNotIn(categories);

Cas d'usage:

  • Filtrer par plusieurs catégories
  • Exclure certains statuts
  • Rechercher par plusieurs IDs

6. IsNull / IsNotNull (Valeurs nulles)​

Vérifier si un champ est null:

// IS NULL
List<Product> findByDiscountIsNull();
// SQL: WHERE discount IS NULL

// IS NOT NULL (ou NotNull)
List<Product> findByDiscountIsNotNull();
List<Product> findByDiscountNotNull();
// SQL: WHERE discount IS NOT NULL

Exemples:

// Produits sans réduction
productRepo.findByDiscountIsNull();

// Produits avec une réduction
productRepo.findByDiscountIsNotNull();

Cas d'usage:

  • Produits sans image
  • Commandes sans date de livraison
  • Utilisateurs sans email

7. True / False (Booléens)​

Vérifier des valeurs booléennes:

// TRUE
List<Product> findByActiveTrue();
// SQL: WHERE active = true

// FALSE
List<Product> findByActiveFalse();
// SQL: WHERE active = false

Exemples:

// Produits actifs
productRepo.findByActiveTrue();

// Produits inactifs
productRepo.findByActiveFalse();

Cas d'usage:

  • Produits actifs/inactifs
  • Utilisateurs vérifiés/non vérifiés
  • Commandes payées/non payées

8. IgnoreCase (Ignorer la casse)​

Recherche insensible à la casse:

// Un seul champ
List<Product> findByNameIgnoreCase(String name);
// SQL: WHERE UPPER(name) = UPPER(?)

// Plusieurs champs
List<Product> findByNameAndCategoryAllIgnoreCase(String name, String category);
// SQL: WHERE UPPER(name) = UPPER(?) AND UPPER(category) = UPPER(?)

Exemples:

// Trouve "laptop", "LAPTOP", "Laptop", etc.
productRepo.findByNameIgnoreCase("laptop");

Cas d'usage:


9. OrderBy (Tri)​

Trier les résultats:

// Tri ascendant
List<Product> findByCategoryOrderByPriceAsc(String category);
// SQL: WHERE category = ? ORDER BY price ASC

// Tri descendant
List<Product> findByCategoryOrderByPriceDesc(String category);
// SQL: WHERE category = ? ORDER BY price DESC

// Tri multiple
List<Product> findByCategoryOrderByPriceAscNameDesc(String category);
// SQL: WHERE category = ? ORDER BY price ASC, name DESC

Exemples:

// Laptops du moins cher au plus cher
productRepo.findByCategoryOrderByPriceAsc("Laptops");

// Laptops du plus cher au moins cher
productRepo.findByCategoryOrderByPriceDesc("Laptops");

Combinaisons Puissantes​

Exemple 1: Recherche Complexe E-commerce​

public interface ProductRepository extends JpaRepository<Product, Long> {

// Produits actifs, dans une fourchette de prix, triés par nom
List<Product> findByActiveTrueAndPriceBetweenOrderByNameAsc(
Double minPrice,
Double maxPrice
);
// SQL: WHERE active = true
// AND price BETWEEN ? AND ?
// ORDER BY name ASC
}

Utilisation:

// Produits actifs entre 100€ et 500€, triés par nom
productRepo.findByActiveTrueAndPriceBetweenOrderByNameAsc(100.0, 500.0);

Exemple 2: Gestion de Stock​

public interface ProductRepository extends JpaRepository<Product, Long> {

// Produits en rupture de stock dans une catégorie
List<Product> findByCategoryAndStockLessThan(String category, Integer minStock);
// SQL: WHERE category = ? AND stock < ?

// Produits avec stock disponible, excluant certaines catégories
List<Product> findByStockGreaterThanAndCategoryNotIn(
Integer minStock,
List<String> excludedCategories
);
// SQL: WHERE stock > ? AND category NOT IN (?, ?, ?)
}

Exemple 3: Recherche Utilisateurs​

public interface UserRepository extends JpaRepository<User, Long> {

// Utilisateurs actifs avec email vérifié
List<User> findByActiveTrueAndEmailVerifiedTrue();

// Utilisateurs créés dans une période
List<User> findByCreatedAtBetween(LocalDate start, LocalDate end);

// Utilisateurs avec nom contenant un mot-clé (insensible à la casse)
List<User> findByNameContainingIgnoreCase(String keyword);
}

Tableau Récapitulatif des 15+ Mots-Clés​

Mot-cléSyntaxeSQLUsage
AndfindByNameAndPriceWHERE name = ? AND price = ?Combiner conditions
OrfindByNameOrCategoryWHERE name = ? OR category = ?Alternative
BetweenfindByPriceBetweenWHERE price BETWEEN ? AND ?Intervalle
LessThanfindByPriceLessThanWHERE price < ?Inférieur
LessThanEqualfindByPriceLessThanEqualWHERE price <= ?Inférieur ou égal
GreaterThanfindByPriceGreaterThanWHERE price > ?Supérieur
GreaterThanEqualfindByPriceGreaterThanEqualWHERE price >= ?Supérieur ou égal
LikefindByNameLikeWHERE name LIKE ?Pattern avec %
ContainingfindByNameContainingWHERE name LIKE %?%Contient
StartingWithfindByNameStartingWithWHERE name LIKE ?%Commence par
EndingWithfindByNameEndingWithWHERE name LIKE %?Finit par
InfindByCategoryInWHERE category IN (?)Dans liste
NotInfindByCategoryNotInWHERE category NOT IN (?)Pas dans liste
IsNullfindByDiscountIsNullWHERE discount IS NULLEst null
IsNotNullfindByDiscountIsNotNullWHERE discount IS NOT NULLN'est pas null
TruefindByActiveTrueWHERE active = trueVrai
FalsefindByActiveFalseWHERE active = falseFaux
IgnoreCasefindByNameIgnoreCaseWHERE UPPER(name) = UPPER(?)Insensible casse
OrderByfindByOrderByPriceAscORDER BY price ASCTri

Conseils et Bonnes Pratiques​

1. Noms de Méthodes Lisibles​

✅ BON:

findByPriceBetweenAndCategoryOrderByNameAsc
  • Lisible
  • Clair
  • Suit les conventions

❌ MAUVAIS:

findByPAndC  // Trop court
findProductsWherePriceIsBetweenMinAndMaxAndCategoryEqualsGivenCategoryOrderedByName // Trop long

2. Limiter la Complexité​

Si la méthode devient trop complexe, utilisez @Query:

// ❌ Trop complexe
findByActiveTrueAndPriceBetweenAndCategoryInAndStockGreaterThanAndNameContainingOrderByPriceAscNameDesc

// ✅ Utilisez @Query à la place
@Query("SELECT p FROM Product p WHERE p.active = true AND ...")
List<Product> findComplexQuery(...);

3. Tester les Méthodes​

@Test
public void testFindByPriceBetween() {
// Arrange
productRepo.save(new Product("Cheap", 50.0));
productRepo.save(new Product("Medium", 150.0));
productRepo.save(new Product("Expensive", 500.0));

// Act
List<Product> results = productRepo.findByPriceBetween(100.0, 200.0);

// Assert
assertEquals(1, results.size());
assertEquals("Medium", results.get(0).getName());
}

Résumé du Chapitre​

Ce que Vous Avez Appris​

✅ 15+ mots-clés pour créer des requêtes
✅ Combinaisons de mots-clés
✅ Recherche textuelle (Like, Containing, etc.)
✅ Comparaisons (LessThan, GreaterThan, Between)
✅ Listes (In, NotIn)
✅ Null (IsNull, IsNotNull)
✅ Booléens (True, False)
✅ Tri (OrderBy)

Maintenant Vous Pouvez​

// Créer des requêtes complexes sans SQL!
List<Product> findByActiveTrueAndPriceBetweenAndCategoryInOrderByPriceAsc(
Double min,
Double max,
List<String> categories
);

Auto-Évaluation​

Créez mentalement la méthode pour:

  1. Trouver les produits entre 100€ et 500€
  2. Trouver les produits contenant "phone" dans le nom
  3. Trouver les produits actifs avec stock > 10
  4. Trouver les utilisateurs créés après une date
  5. Trouver les commandes non payées

Réponses:

  1. findByPriceBetween(Double min, Double max)
  2. findByNameContaining(String keyword)
  3. findByActiveTrueAndStockGreaterThan(Integer minStock)
  4. findByCreatedAtAfter(LocalDate date)
  5. findByPaidFalse()

Prochaine Étape​

Vous maîtrisez les conventions de nommage! Passez aux Relations entre Entités.

➡️ Chapitre 2: Relations entre Entités

⬅️ Retour au Module 6