Posted on: July 2, 2025 Posted by: rahulgite Comments: 0

This guide provides an end-to-end explanation of Spring Data JPA including project setup, entity creation, repository interfaces, query methods, JPA architecture, persistence lifecycle, and JPQL examples. It also includes diagrams and best practices.


1. Project Setup

Start with Spring Initializr (start.spring.io) and add the following dependencies:

  • Spring Web
  • Spring Data JPA
  • H2 Database (for testing)

Project Structure:

com.example.applicant
├── controller
│   └── ApplicantController.java
├── service
│   └── ApplicantService.java
├── repository
│   └── ApplicantRepository.java
└── model
    └── Applicant.java

2. JPA Architecture Overview

Key Components:

  • Persistence Unit: A logical grouping of all entity classes.
  • Persistence.xml: Configuration for JPA (Spring Boot uses application.properties or application.yml).
  • Persistence Provider (Hibernate): Implements JPA specifications.
  • EntityManagerFactory: Creates EntityManager instances.
  • EntityManager: Performs operations on entities.
  • Persistence Context: First-level cache for managed entities.
  • Entity: Java POJO mapped to a DB table.

Flow Diagram:

Application
   ↓
Specification Repository (Optional)
   ↓
JpaRepository / CrudRepository
   ↓
EntityManager
   ↓
Persistence Context
   ↓
Database

3. Persistence Lifecycle States

States of a JPA Entity:

StateDescription
NewNot yet persisted
ManagedTracked by EntityManager
DetachedNo longer tracked
RemovedMarked for deletion

State Transitions:

  • New → Managed → Detached → Removed
  • Use persist(), merge(), detach(), remove()

4. Entity Definition and Annotations

@Entity
public class Applicant {
  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private Long id;

  private String name;
  private String status;
}

Common Annotations:

  • @Entity: Declares JPA entity.
  • @Id: Primary key.
  • @GeneratedValue: Auto ID generation.
  • @Column, @Table: Customize mapping.

5. Repository Interfaces

CrudRepository

public interface ApplicantRepository extends CrudRepository<Applicant, Long> {}

PagingAndSortingRepository

Pageable pageable = PageRequest.of(0, 5);
Page<Applicant> applicants = repository.findAll(pageable);

JpaRepository

public interface ApplicantRepository extends JpaRepository<Applicant, Long> {}

Specification Repository (Dynamic Filtering)

Used for dynamic and complex queries using criteria.

public interface ApplicantRepository extends JpaRepository<Applicant, Long>, JpaSpecificationExecutor<Applicant> {}
Specification<Applicant> hasStatus(String status) = (root, query, builder) ->
    builder.equal(root.get("status"), status);

Repository Hierarchy:

JpaRepository
├── PagingAndSortingRepository
│   └── CrudRepository
└── JpaSpecificationExecutor (optional)

6. Query Methods and Custom Queries

Interface-Based Query Method Examples:

Spring Data JPA automatically implements query logic based on method naming conventions in repository interfaces.

You can combine multiple keywords like IgnoreCase, Containing, StartingWith, etc., to build expressive and powerful query methods.

Spring Data JPA automatically implements query logic based on method naming conventions in repository interfaces.

List<Applicant> findByStatus(String status);
List<Applicant> findByNameAndStatus(String name, String status);
List<Applicant> findByStatusOrderByNameAsc(String status);
/ Finds applicants with exact name
List<Applicant> findByName(String name);

// Finds applicants with name exactly (case-insensitive)
List<Applicant> findByNameIgnoreCase(String name);

// Finds applicants whose name contains the given string (case-sensitive)
List<Applicant> findByNameContaining(String keyword);

// Finds applicants whose name contains the string, case-insensitive
List<Applicant> findByNameContainingIgnoreCase(String keyword);

// Finds applicants with name starting with a prefix (case-insensitive)
List<Applicant> findByNameStartingWithIgnoreCase(String prefix);

// Combines name containing + status filter + ignore case
List<Applicant> findByNameContainingIgnoreCaseAndStatusIgnoreCase(String name, String status);

// Finds applicants by name ignoring case
List<Applicant> findByNameIgnoreCase(String name);

// Finds applicants whose name contains the given string
List<Applicant> findByNameContaining(String keyword);

// Finds applicants with name starting with a prefix
List<Applicant> findByNameStartingWith(String prefix);

// Finds applicants with status and name
List<Applicant> findByNameAndStatus(String name, String status);

// Finds applicants with either of two statuses
List<Applicant> findByStatusOrStatus(String status1, String status2);

// Finds applicants with ID between two values
List<Applicant> findByIdBetween(Long start, Long end);

// Finds applicants with status in a list
List<Applicant> findByStatusIn(List<String> statuses);

// Finds all applicants ordered by name ascending
List<Applicant> findAllByOrderByNameAsc();

JPQL Using @Query:

@Query("SELECT a FROM Applicant a WHERE a.name LIKE %:name%")
List<Applicant> searchByPartialName(@Param("name") String name);

@Query("SELECT a FROM Applicant a WHERE a.status = :status")
List<Applicant> findByStatusJPQL(@Param("status") String status);

// WHERE and AND
@Query("SELECT a FROM Applicant a WHERE a.status = 'active' AND a.name = 'John'")
List<Applicant> activeNamedJohn();

// OR
@Query("SELECT a FROM Applicant a WHERE a.status = 'active' OR a.status = 'pending'")
List<Applicant> activeOrPending();

// BETWEEN
@Query("SELECT a FROM Applicant a WHERE a.id BETWEEN :start AND :end")
List<Applicant> findInRange(@Param("start") Long start, @Param("end") Long end);

// IN
@Query("SELECT a FROM Applicant a WHERE a.status IN :statuses")
List<Applicant> findByStatuses(@Param("statuses") List<String> statuses);

// ORDER BY
@Query("SELECT a FROM Applicant a ORDER BY a.name ASC")
List<Applicant> findAllSortedByName();

// LIKE with wildcard
@Query("SELECT a FROM Applicant a WHERE a.name LIKE :pattern")
List<Applicant> findByPattern(@Param("pattern") String pattern);

7. Repository Comparison

Spring Data JPA offers multiple repository interfaces with increasing levels of functionality. Here’s a detailed comparison:

Repository InterfaceExtendsKey FeaturesReturn Type
CrudRepositoryBasic CRUD methods like save, findById, deleteByIdOptional, Iterable
PagingAndSortingRepositoryCrudRepositoryAdds pagination and sorting methods (findAll(Pageable), findAll(Sort))Page, Sort
JpaRepositoryPagingAndSortingRepositoryAdds batch operations (flush, saveAllAndFlush) and JPA-specific featuresList, Optional, Page
ListCrudRepository– (Spring Data 3+)Same as CrudRepository but returns List instead of IterableList
ListPagingAndSortingRepositoryListCrudRepositoryLike PagingAndSortingRepository, but returns List instead of Iterable or PageList
JpaSpecificationExecutor– (used alongside JpaRepository)Allows building dynamic queries using the Criteria APIList, Page

Common JPA Annotations:

  • @Entity: Marks a class as a persistent entity.
  • @Table(name = "applicants"): Specifies the table name for the entity.
  • @Id: Specifies the primary key field.
  • @GeneratedValue(strategy = ...): Defines how the primary key is generated.
  • @Column(name = "applicant_name"): Maps a field to a specific column.
  • @Transient: Marks a field not to be persisted.
  • @Embedded: Marks a field as an embeddable type.
  • @Embeddable: Marks a class whose fields can be embedded in an entity.
  • @Enumerated(EnumType.STRING): Used for enum mapping to string or ordinal.
  • @Lob: Used for large objects like CLOB/BLOB.
  • @Temporal(TemporalType.DATE): Used with Date or Calendar to specify the precision.

Spring Data & Query Annotations:

  • @Query: Allows defining custom JPQL or native SQL inside repository interfaces.
  • @Param: Used to bind method parameters to query parameters.
  • @Modifying: Indicates that the query method modifies data (e.g., update, delete).
  • @Transactional: Manages transaction boundaries in methods. Needed with @Modifying.
  • @EnableJpaRepositories: Enables JPA repositories and scanning.
  • @Repository: Marks an interface or class as a Spring-managed data component.

Leave a Comment