Saltar al contenido principal

Capítulo 1: Convenciones de Nombres Avanzadas

Introducción​

En el Módulo 2, aprendió 3 palabras clave simples: findBy, And, Or.

¡Ahora aprenderá más de 15 palabras clave adicionales para crear consultas complejas!

Lo que va a aprender​

  1. Las 15+ palabras clave de Spring Data JPA
  2. Cómo combinarlas
  3. Ejemplos para cada palabra clave

Duración: 1h


¿Cómo Funciona?​

Principio Mágico de Spring Data JPA​

public interface ProductRepository extends JpaRepository<Product, Long> {

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

¡Spring lee el nombre del método y genera el SQL automáticamente!

-- SQL generado automáticamente:
SELECT * FROM product WHERE price < ?

¡Usted NO escribe SQL, Spring lo hace por usted!


Estructura de los Nombres de Métodos​

findBy + [Campo] + [Operación] + [OtroCampo] + [Operación]

Ejemplos:

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

Las 15+ Palabras Clave​

1. And / Or (Ya las conoce)​

Combinar varias condiciones:

// 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 = ?

Ejemplo concreto:

// Encontrar un producto "Laptop" a 999.99€
productRepo.findByNameAndPrice("Laptop", 999.99);

2. Between (Entre dos valores)​

Encontrar valores en un intervalo:

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

Ejemplo:

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

Casos de uso:

  • Precio en un rango
  • Fechas entre dos momentos
  • Edades entre mínimo y máximo

3. LessThan / GreaterThan (Comparaciones)​

Comparar valores numéricos o fechas:

// Menor que
List<Product> findByPriceLessThan(Double maxPrice);
// SQL: WHERE price < ?

// Menor o igual
List<Product> findByPriceLessThanEqual(Double maxPrice);
// SQL: WHERE price <= ?

// Mayor que
List<Product> findByPriceGreaterThan(Double minPrice);
// SQL: WHERE price > ?

// Mayor o igual
List<Product> findByPriceGreaterThanEqual(Double minPrice);
// SQL: WHERE price >= ?

Ejemplos:

// Productos a menos de 100€
productRepo.findByPriceLessThan(100.0);

// Productos a 100€ o menos
productRepo.findByPriceLessThanEqual(100.0);

// Productos a más de 1000€
productRepo.findByPriceGreaterThan(1000.0);

Casos de uso:

  • Precio mínimo/máximo
  • Stock mínimo
  • Edad mínima/máxima
  • Fechas antes/después

4. Like / Containing / StartingWith / EndingWith (Búsqueda de Texto)​

Buscar en cadenas de texto:

// LIKE (usted proporciona los %)
List<Product> findByNameLike(String pattern);
// SQL: WHERE name LIKE ?
// Uso: findByNameLike("%Laptop%")

// CONTAINING (Spring agrega los % automáticamente)
List<Product> findByNameContaining(String keyword);
// SQL: WHERE name LIKE ?
// Uso: findByNameContaining("Laptop")
// Busca: %Laptop%

// STARTING WITH (busca al inicio)
List<Product> findByNameStartingWith(String prefix);
// SQL: WHERE name LIKE ?
// Uso: findByNameStartingWith("Mac")
// Busca: Mac%

// ENDING WITH (busca al final)
List<Product> findByNameEndingWith(String suffix);
// SQL: WHERE name LIKE ?
// Uso: findByNameEndingWith("Pro")
// Busca: %Pro

Ejemplos:

// Productos que contienen "phone" (iPhone, smartphone, etc.)
productRepo.findByNameContaining("phone");

// Productos que comienzan con "Mac" (MacBook, Mac Mini, etc.)
productRepo.findByNameStartingWith("Mac");

// Productos que terminan con "Pro" (MacBook Pro, iPad Pro, etc.)
productRepo.findByNameEndingWith("Pro");

Diferencia Like vs Containing:

// Like - usted controla los %
findByNameLike("%Laptop%") // Contiene Laptop
findByNameLike("Laptop%") // Comienza con Laptop
findByNameLike("%Laptop") // Termina con Laptop

// Containing - Spring agrega los %
findByNameContaining("Laptop") // Contiene Laptop (%Laptop%)

5. In / NotIn (En una lista)​

Verificar si un valor está en una lista:

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

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

Ejemplos:

// Productos en varias categorías
List<String> categories = Arrays.asList("Electronics", "Computers", "Phones");
productRepo.findByCategoryIn(categories);

// Productos NO en estas categorías
productRepo.findByCategoryNotIn(categories);

Casos de uso:

  • Filtrar por varias categorías
  • Excluir ciertos estados
  • Buscar por varios IDs

6. IsNull / IsNotNull (Valores nulos)​

Verificar si un campo es null:

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

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

Ejemplos:

// Productos sin descuento
productRepo.findByDiscountIsNull();

// Productos con descuento
productRepo.findByDiscountIsNotNull();

Casos de uso:

  • Productos sin imagen
  • Pedidos sin fecha de entrega
  • Usuarios sin email

7. True / False (Booleanos)​

Verificar valores booleanos:

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

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

Ejemplos:

// Productos activos
productRepo.findByActiveTrue();

// Productos inactivos
productRepo.findByActiveFalse();

Casos de uso:

  • Productos activos/inactivos
  • Usuarios verificados/no verificados
  • Pedidos pagados/no pagados

8. IgnoreCase (Ignorar mayúsculas/minúsculas)​

Búsqueda insensible a mayúsculas/minúsculas:

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

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

Ejemplos:

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

Casos de uso:


9. OrderBy (Ordenar)​

Ordenar los resultados:

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

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

// Orden múltiple
List<Product> findByCategoryOrderByPriceAscNameDesc(String category);
// SQL: WHERE category = ? ORDER BY price ASC, name DESC

Ejemplos:

// Laptops del más barato al más caro
productRepo.findByCategoryOrderByPriceAsc("Laptops");

// Laptops del más caro al más barato
productRepo.findByCategoryOrderByPriceDesc("Laptops");

Combinaciones Potentes​

Ejemplo 1: Búsqueda Compleja E-commerce​

public interface ProductRepository extends JpaRepository<Product, Long> {

// Productos activos, en un rango de precios, ordenados por nombre
List<Product> findByActiveTrueAndPriceBetweenOrderByNameAsc(
Double minPrice,
Double maxPrice
);
// SQL: WHERE active = true
// AND price BETWEEN ? AND ?
// ORDER BY name ASC
}

Uso:

// Productos activos entre 100€ y 500€, ordenados por nombre
productRepo.findByActiveTrueAndPriceBetweenOrderByNameAsc(100.0, 500.0);

Ejemplo 2: Gestión de Inventario​

public interface ProductRepository extends JpaRepository<Product, Long> {

// Productos agotados en una categoría
List<Product> findByCategoryAndStockLessThan(String category, Integer minStock);
// SQL: WHERE category = ? AND stock < ?

// Productos con stock disponible, excluyendo ciertas categorías
List<Product> findByStockGreaterThanAndCategoryNotIn(
Integer minStock,
List<String> excludedCategories
);
// SQL: WHERE stock > ? AND category NOT IN (?, ?, ?)
}

Ejemplo 3: Búsqueda de Usuarios​

public interface UserRepository extends JpaRepository<User, Long> {

// Usuarios activos con email verificado
List<User> findByActiveTrueAndEmailVerifiedTrue();

// Usuarios creados en un periodo
List<User> findByCreatedAtBetween(LocalDate start, LocalDate end);

// Usuarios con nombre que contiene una palabra clave (insensible a mayúsculas/minúsculas)
List<User> findByNameContainingIgnoreCase(String keyword);
}

Tabla Resumen de las 15+ Palabras Clave​

Palabra claveSintaxisSQLUso
AndfindByNameAndPriceWHERE name = ? AND price = ?Combinar condiciones
OrfindByNameOrCategoryWHERE name = ? OR category = ?Alternativa
BetweenfindByPriceBetweenWHERE price BETWEEN ? AND ?Intervalo
LessThanfindByPriceLessThanWHERE price < ?Menor
LessThanEqualfindByPriceLessThanEqualWHERE price <= ?Menor o igual
GreaterThanfindByPriceGreaterThanWHERE price > ?Mayor
GreaterThanEqualfindByPriceGreaterThanEqualWHERE price >= ?Mayor o igual
LikefindByNameLikeWHERE name LIKE ?Patrón con %
ContainingfindByNameContainingWHERE name LIKE %?%Contiene
StartingWithfindByNameStartingWithWHERE name LIKE ?%Comienza con
EndingWithfindByNameEndingWithWHERE name LIKE %?Termina con
InfindByCategoryInWHERE category IN (?)En lista
NotInfindByCategoryNotInWHERE category NOT IN (?)No en lista
IsNullfindByDiscountIsNullWHERE discount IS NULLEs null
IsNotNullfindByDiscountIsNotNullWHERE discount IS NOT NULLNo es null
TruefindByActiveTrueWHERE active = trueVerdadero
FalsefindByActiveFalseWHERE active = falseFalso
IgnoreCasefindByNameIgnoreCaseWHERE UPPER(name) = UPPER(?)Insensible a mayúsculas/minúsculas
OrderByfindByOrderByPriceAscORDER BY price ASCOrdenar

Consejos y Buenas Prácticas​

1. Nombres de Métodos Legibles​

✅ BUENO:

findByPriceBetweenAndCategoryOrderByNameAsc
  • Legible
  • Claro
  • Sigue las convenciones

❌ MALO:

findByPAndC  // Demasiado corto
findProductsWherePriceIsBetweenMinAndMaxAndCategoryEqualsGivenCategoryOrderedByName // Demasiado largo

2. Limitar la Complejidad​

Si el método se vuelve demasiado complejo, utilice @Query:

// ❌ Demasiado complejo
findByActiveTrueAndPriceBetweenAndCategoryInAndStockGreaterThanAndNameContainingOrderByPriceAscNameDesc

// ✅ Utilice @Query en su lugar
@Query("SELECT p FROM Product p WHERE p.active = true AND ...")
List<Product> findComplexQuery(...);

3. Probar los Métodos​

@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());
}

Resumen del Capítulo​

Lo que Ha Aprendido​

✅ 15+ palabras clave para crear consultas
✅ Combinaciones de palabras clave
✅ Búsqueda de texto (Like, Containing, etc.)
✅ Comparaciones (LessThan, GreaterThan, Between)
✅ Listas (In, NotIn)
✅ Null (IsNull, IsNotNull)
✅ Booleanos (True, False)
✅ Ordenar (OrderBy)

Ahora Puede​

// ¡Crear consultas complejas sin SQL!
List<Product> findByActiveTrueAndPriceBetweenAndCategoryInOrderByPriceAsc(
Double min,
Double max,
List<String> categories
);

Autoevaluación​

Mentalmente cree el método para:

  1. Encontrar los productos entre 100€ y 500€
  2. Encontrar los productos que contienen "phone" en el nombre
  3. Encontrar los productos activos con stock > 10
  4. Encontrar los usuarios creados después de una fecha
  5. Encontrar los pedidos no pagados

Respuestas:

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

Próximo Paso​

¡Usted domina las convenciones de nombres! Continúe con las Relaciones entre Entidades.

➡️ Capítulo 2: Relaciones entre Entidades

⬅️ Volver al Módulo 6