Spring Boot Repository Pattern

A repository is the layer between your application and the database. Spring Data JPA generates the implementation automatically — you define an interface, and Spring provides all the database methods.

Without a Repository (Old Way)

// Writing raw SQL manually — tedious and error-prone
String sql = "SELECT * FROM users WHERE id = ?";
PreparedStatement stmt = connection.prepareStatement(sql);
stmt.setLong(1, id);
ResultSet rs = stmt.executeQuery();
User user = new User();
user.setId(rs.getLong("id"));
user.setName(rs.getString("name"));
// ...and 20 more lines

With Spring Data JPA Repository

public interface UserRepository extends JpaRepository<User, Long> {
    // That's it. Spring generates all CRUD methods automatically.
}

Spring reads this interface and creates a full working implementation at startup. No SQL required.

Built-in Methods from JpaRepository

Method                          What It Does
────────────────────────────    ──────────────────────────────────────
save(entity)                    Insert or update a record
findById(id)                    Get one record by primary key
findAll()                       Get all records
deleteById(id)                  Delete a record by primary key
count()                         Count total records
existsById(id)                  Check if a record exists
findAll(Pageable pageable)       Get records with pagination

Repository Hierarchy

Repository
    │ (extends)
CrudRepository         ← Basic CRUD: save, find, delete
    │ (extends)
PagingAndSortingRepository  ← Adds pagination and sorting
    │ (extends)
JpaRepository          ← Adds batch ops, flush, JPA-specific features

Use JpaRepository — it gives you everything.

Derived Query Methods

Spring Data generates SQL from the method name you write in the interface. The method name is the query:

public interface UserRepository extends JpaRepository<User, Long> {

    // SELECT * FROM users WHERE email = ?
    User findByEmail(String email);

    // SELECT * FROM users WHERE name = ? AND age > ?
    List<User> findByNameAndAgeGreaterThan(String name, int age);

    // SELECT * FROM users WHERE name LIKE '%keyword%'
    List<User> findByNameContaining(String keyword);

    // SELECT * FROM users WHERE active = true ORDER BY name ASC
    List<User> findByActiveTrueOrderByNameAsc();

    // SELECT COUNT(*) FROM users WHERE role = ?
    long countByRole(String role);

    // DELETE FROM users WHERE email = ?
    void deleteByEmail(String email);
}

Derived Query Keyword Reference

Keyword             SQL Equivalent            Example
──────────────      ─────────────────         ──────────────────────────────
findBy              WHERE                     findByName
And                 AND                       findByNameAndAge
Or                  OR                        findByNameOrEmail
Like                LIKE                      findByNameLike
Containing          LIKE '%x%'                findByNameContaining
StartingWith        LIKE 'x%'                 findByNameStartingWith
GreaterThan         >                         findByAgeGreaterThan
LessThan            <                         findByAgeLessThan
Between             BETWEEN                   findByAgeBetween
OrderBy             ORDER BY                  findByRoleOrderByNameAsc
IsNull              IS NULL                   findByDeletedAtIsNull
True / False        = true / = false          findByActiveTrue

Custom Queries with @Query

When derived method names get too long or the query is complex, write JPQL (Java-style SQL) directly:

@Query("SELECT u FROM User u WHERE u.email = :email AND u.active = true")
Optional<User> findActiveUserByEmail(@Param("email") String email);

// Native SQL (use sparingly — ties you to a specific database)
@Query(value = "SELECT * FROM users WHERE created_at > :date",
       nativeQuery = true)
List<User> findUsersCreatedAfter(@Param("date") LocalDate date);

Using the Repository in a Service

@Service
public class UserService {

    private final UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public User findById(Long id) {
        return userRepository.findById(id)
            .orElseThrow(() -> new UserNotFoundException(id));
    }

    public User save(User user) {
        return userRepository.save(user);
    }

    public List<User> search(String name) {
        return userRepository.findByNameContaining(name);
    }
}

Summary

  • Extend JpaRepository<Entity, ID> to get all CRUD methods for free
  • Spring generates the implementation — you only write the interface
  • Derived query methods turn method names into SQL automatically
  • Use @Query for complex queries that derived names cannot express
  • Always inject and use the repository through a service class

Leave a Comment

Your email address will not be published. Required fields are marked *