Skip to main content

Chapter 1: Advanced Naming Conventions

Introduction​

In Module 2, you learned 3 simple keywords: findBy, And, Or.

Now, you will learn 15+ additional keywords to create complex queries!

What You Will Learn​

  1. The 15+ Spring Data JPA keywords
  2. How to combine them
  3. Examples for each keyword

Duration: 1h


How Does It Work?​

The Magic Principle of Spring Data JPA​

public interface ProductRepository extends JpaRepository<Product, Long> {

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

Spring reads the method name and generates the SQL automatically!

-- Automatically generated SQL:
SELECT * FROM product WHERE price < ?

You do NOT write SQL, Spring does it for you!


Method Name Structure​

findBy + [Field] + [Operation] + [OtherField] + [Operation]

Examples:

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

The 15+ Keywords​

1. And / Or (You Already Know)​

Combine multiple 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 = ?

Concrete example:

// Find a "Laptop" product at €999.99
productRepo.findByNameAndPrice("Laptop", 999.99);

2. Between (Between two values)​

Find values within a range:

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

Example:

// Products between €100 and €500
List<Product> products = productRepo.findByPriceBetween(100.0, 500.0);

Use cases:

  • Price within a range
  • Dates between two moments
  • Ages between min and max

3. LessThan / GreaterThan (Comparisons)​

Compare numeric values or dates:

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

// Less than or equal
List<Product> findByPriceLessThanEqual(Double maxPrice);
// SQL: WHERE price <= ?

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

// Greater than or equal
List<Product> findByPriceGreaterThanEqual(Double minPrice);
// SQL: WHERE price >= ?

Examples:

// Products less than €100
productRepo.findByPriceLessThan(100.0);

// Products €100 or less
productRepo.findByPriceLessThanEqual(100.0);

// Products more than €1000
productRepo.findByPriceGreaterThan(1000.0);

Use cases:

  • Min/max price
  • Minimum stock
  • Minimum/maximum age
  • Dates before/after

Search within strings:

// LIKE (you provide the %)
List<Product> findByNameLike(String pattern);
// SQL: WHERE name LIKE ?
// Usage: findByNameLike("%Laptop%")

// CONTAINING (Spring adds the % automatically)
List<Product> findByNameContaining(String keyword);
// SQL: WHERE name LIKE ?
// Usage: findByNameContaining("Laptop")
// Searches: %Laptop%

// STARTING WITH (searches at the beginning)
List<Product> findByNameStartingWith(String prefix);
// SQL: WHERE name LIKE ?
// Usage: findByNameStartingWith("Mac")
// Searches: Mac%

// ENDING WITH (searches at the end)
List<Product> findByNameEndingWith(String suffix);
// SQL: WHERE name LIKE ?
// Usage: findByNameEndingWith("Pro")
// Searches: %Pro

Examples:

// Products containing "phone" (iPhone, smartphone, etc.)
productRepo.findByNameContaining("phone");

// Products starting with "Mac" (MacBook, Mac Mini, etc.)
productRepo.findByNameStartingWith("Mac");

// Products ending with "Pro" (MacBook Pro, iPad Pro, etc.)
productRepo.findByNameEndingWith("Pro");

Difference Like vs Containing:

// Like - you control the %
findByNameLike("%Laptop%") // Contains Laptop
findByNameLike("Laptop%") // Starts with Laptop
findByNameLike("%Laptop") // Ends with Laptop

// Containing - Spring adds the %
findByNameContaining("Laptop") // Contains Laptop (%Laptop%)

5. In / NotIn (In a list)​

Check if a value is in a list:

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

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

Examples:

// Products in multiple categories
List<String> categories = Arrays.asList("Electronics", "Computers", "Phones");
productRepo.findByCategoryIn(categories);

// Products NOT in these categories
productRepo.findByCategoryNotIn(categories);

Use cases:

  • Filter by multiple categories
  • Exclude certain statuses
  • Search by multiple IDs

6. IsNull / IsNotNull (Null values)​

Check if a field is null:

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

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

Examples:

// Products without discount
productRepo.findByDiscountIsNull();

// Products with a discount
productRepo.findByDiscountIsNotNull();

Use cases:

  • Products without image
  • Orders without delivery date
  • Users without email

7. True / False (Booleans)​

Check boolean values:

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

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

Examples:

// Active products
productRepo.findByActiveTrue();

// Inactive products
productRepo.findByActiveFalse();

Use cases:

  • Active/inactive products
  • Verified/unverified users
  • Paid/unpaid orders

8. IgnoreCase (Ignore case)​

Case-insensitive search:

// Single field
List<Product> findByNameIgnoreCase(String name);
// SQL: WHERE UPPER(name) = UPPER(?)

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

Examples:

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

Use cases:


9. OrderBy (Sorting)​

Sort results:

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

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

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

Examples:

// Laptops from cheapest to most expensive
productRepo.findByCategoryOrderByPriceAsc("Laptops");

// Laptops from most expensive to cheapest
productRepo.findByCategoryOrderByPriceDesc("Laptops");

Powerful Combinations​

public interface ProductRepository extends JpaRepository<Product, Long> {

// Active products, within a price range, sorted by name
List<Product> findByActiveTrueAndPriceBetweenOrderByNameAsc(
Double minPrice,
Double maxPrice
);
// SQL: WHERE active = true
// AND price BETWEEN ? AND ?
// ORDER BY name ASC
}

Usage:

// Active products between €100 and €500, sorted by name
productRepo.findByActiveTrueAndPriceBetweenOrderByNameAsc(100.0, 500.0);

Example 2: Stock Management​

public interface ProductRepository extends JpaRepository<Product, Long> {

// Out of stock products in a category
List<Product> findByCategoryAndStockLessThan(String category, Integer minStock);
// SQL: WHERE category = ? AND stock < ?

// Products with available stock, excluding certain categories
List<Product> findByStockGreaterThanAndCategoryNotIn(
Integer minStock,
List<String> excludedCategories
);
// SQL: WHERE stock > ? AND category NOT IN (?, ?, ?)
}

public interface UserRepository extends JpaRepository<User, Long> {

// Active users with verified email
List<User> findByActiveTrueAndEmailVerifiedTrue();

// Users created within a period
List<User> findByCreatedAtBetween(LocalDate start, LocalDate end);

// Users with name containing a keyword (case-insensitive)
List<User> findByNameContainingIgnoreCase(String keyword);
}

Summary Table of the 15+ Keywords​

KeywordSyntaxSQLUsage
AndfindByNameAndPriceWHERE name = ? AND price = ?Combine conditions
OrfindByNameOrCategoryWHERE name = ? OR category = ?Alternative
BetweenfindByPriceBetweenWHERE price BETWEEN ? AND ?Range
LessThanfindByPriceLessThanWHERE price < ?Less than
LessThanEqualfindByPriceLessThanEqualWHERE price <= ?Less than or equal
GreaterThanfindByPriceGreaterThanWHERE price > ?Greater than
GreaterThanEqualfindByPriceGreaterThanEqualWHERE price >= ?Greater than or equal
LikefindByNameLikeWHERE name LIKE ?Pattern with %
ContainingfindByNameContainingWHERE name LIKE %?%Contains
StartingWithfindByNameStartingWithWHERE name LIKE ?%Starts with
EndingWithfindByNameEndingWithWHERE name LIKE %?Ends with
InfindByCategoryInWHERE category IN (?)In list
NotInfindByCategoryNotInWHERE category NOT IN (?)Not in list
IsNullfindByDiscountIsNullWHERE discount IS NULLIs null
IsNotNullfindByDiscountIsNotNullWHERE discount IS NOT NULLIs not null
TruefindByActiveTrueWHERE active = trueTrue
FalsefindByActiveFalseWHERE active = falseFalse
IgnoreCasefindByNameIgnoreCaseWHERE UPPER(name) = UPPER(?)Case-insensitive
OrderByfindByOrderByPriceAscORDER BY price ASCSorting

Tips and Best Practices​

1. Readable Method Names​

✅ GOOD:

findByPriceBetweenAndCategoryOrderByNameAsc
  • Readable
  • Clear
  • Follows conventions

❌ BAD:

findByPAndC  // Too short
findProductsWherePriceIsBetweenMinAndMaxAndCategoryEqualsGivenCategoryOrderedByName // Too long

2. Limit Complexity​

If the method becomes too complex, use @Query:

// ❌ Too complex
findByActiveTrueAndPriceBetweenAndCategoryInAndStockGreaterThanAndNameContainingOrderByPriceAscNameDesc

// ✅ Use @Query instead
@Query("SELECT p FROM Product p WHERE p.active = true AND ...")
List<Product> findComplexQuery(...);

3. Test the Methods​

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

Chapter Summary​

What You Have Learned​

✅ 15+ keywords to create queries
✅ Combinations of keywords
✅ Text search (Like, Containing, etc.)
✅ Comparisons (LessThan, GreaterThan, Between)
✅ Lists (In, NotIn)
✅ Null (IsNull, IsNotNull)
✅ Booleans (True, False)
✅ Sorting (OrderBy)

Now You Can​

// Create complex queries without SQL!
List<Product> findByActiveTrueAndPriceBetweenAndCategoryInOrderByPriceAsc(
Double min,
Double max,
List<String> categories
);

Self-Assessment​

Mentally create the method for:

  1. Finding products between €100 and €500
  2. Finding products containing "phone" in the name
  3. Finding active products with stock > 10
  4. Finding users created after a date
  5. Finding unpaid orders

Answers:

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

Next Step​

You master naming conventions! Move on to Entity Relationships.

➡️ Chapter 2: Entity Relationships

⬅️ Back to Module 6