Chapter 8: Persistence Layer with Spring Data JPA and Hibernate


In the previous chapter, we implemented request validation and exception handling for our Insurance Policy Management System (IPMS).

Our APIs can now:

  • Validate requests
  • Return standardized errors
  • Handle exceptions gracefully

However, our data is still not stored anywhere.

In this chapter, we will introduce the persistence layer using Spring Data JPA and Hibernate.

By the end of this chapter, our APIs will be capable of storing and retrieving insurance policies from a relational database.


🎯 Learning Objectives

By the end of this chapter, you will be able to:

  • Understand JPA
  • Understand Hibernate
  • Create Entities
  • Create Repositories
  • Perform CRUD operations
  • Configure database connectivity
  • Understand entity relationships
  • Manage transactions

Why Persistence Matters

Without persistence:

Create Policy
      ↓
Application Restarts
      ↓
Data Lost

Persistence ensures data survives application restarts.

For our Insurance Policy Management System we must store:

Policy Holders

Policies

Claims

Premium Payments

Agents

Beneficiaries

JPA and Hibernate Overview

Many developers confuse JPA and Hibernate.

They are not the same.


What is JPA?

JPA stands for:

Java Persistence API

JPA is a specification.

It defines:

  • Entity mapping
  • Persistence operations
  • Relationships
  • Query mechanisms

What is Hibernate?

Hibernate is:

JPA Implementation

It provides the actual persistence engine.


JPA-Hibernate Architecture

JPA Hibernate Architecture


Persistence Architecture

Our application architecture now becomes:

Controller
      ↓
Service
      ↓
Repository
      ↓
Hibernate
      ↓
Database

This follows the layered architecture introduced in Chapter05.


Database Configuration

Spring Boot simplifies database configuration.


application.yml

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/ipms

    username: root

    password: password

  jpa:
    hibernate:
      ddl-auto: update

    show-sql: true

Creating Our First Entity

The first entity will be:

Policy

which we introduced in earlier chapters.


Policy Entity

@Entity

@Table(name = "policies")

public class Policy {

    @Id

    private String policyNumber;

    private String policyType;

    private String status;

    private BigDecimal coverageAmount;

}

Understanding Entity Annotations

@Entity

Marks the class as a database entity.

@Entity
public class Policy {
}

@Table

Maps entity to database table.

@Table(name = "policies")

@Id

Defines the primary key.

@Id
private String policyNumber;

Entity Lifecycle

Every entity goes through a lifecycle.


Entity Lifecycle

Entity Lifecycle


States include:

Transient

Persistent

Detached

Removed

Understanding these states helps diagnose persistence issues.


Policy Entity Model

Our Policy entity contains:

Policy Number

Policy Type

Status

Coverage Amount

Policy Entity Model

Policy Entity Model


Creating Repository Layer

Repositories abstract database access.

Without repositories:

Connection connection =
        DriverManager.getConnection(...);

With Spring Data JPA:

policyRepository.save(policy);

Policy Repository

@Repository

public interface PolicyRepository
        extends JpaRepository<
                Policy,
                String> {

}

Spring automatically generates CRUD operations.


CRUD Operations

The repository automatically provides:

save()

findById()

findAll()

deleteById()

existsById()

No implementation required.


Saving a Policy

Policy policy = new Policy();

policy.setPolicyNumber("LIFE-100001");

policyRepository.save(policy);

Hibernate generates SQL automatically.


Generated SQL

insert into policies
(
  policy_number,
  policy_type
)
values
(
  'LIFE-100001',
  'TERM'
);

Repository Flow

Repository Processing Flow

Repository Flow


Query Methods

Spring Data JPA generates queries automatically.


Find By Status

List<Policy>
findByStatus(String status);

Spring generates SQL automatically.


Find By Policy Type

List<Policy>
findByPolicyType(String policyType);

No SQL required.


Integrating Repository into Service Layer

Service:

@Service
@RequiredArgsConstructor
public class PolicyService {

    private final PolicyRepository
            repository;

}

Create Policy Service

public PolicyResponse createPolicy(
        PolicyRequest request) {

    Policy policy = mapper.toEntity(request);

    repository.save(policy);

    return mapper.toResponse(policy);
}

This is our first real database operation.


Entity Relationships

Insurance systems contain relationships.

Examples:

Policy Holder
      ↓
Policies

Policy
      ↓
Claims

Policy
      ↓
Beneficiaries

Common Relationships

One-To-Many

@OneToMany

Example:

Policy Holder
      ↓
Multiple Policies

Many-To-One

@ManyToOne

Example:

Many Policies
      ↓
One Policy Holder

Entity Relationships

Entity Relationships


Policy Holder Entity

@Entity
public class PolicyHolder {

    @Id
    private Long id;

    private String fullName;

}

Policy Entity Relationship

@ManyToOne

@JoinColumn(
        name = "policy_holder_id")

private PolicyHolder policyHolder;

Hibernate automatically manages foreign keys.


Transactions

Database operations should be atomic.

Example:

Create Policy
      ↓
Create Payment Schedule
      ↓
Create Beneficiaries

Either:

All Succeed

or

All Fail

Transaction Management

Spring provides:

@Transactional

Transaction Example

@Transactional

public void createPolicy() {

    savePolicy();

    saveBeneficiary();

    savePayment();

}

Transaction Processing Flow

Transaction Management Flow


Optimistic Locking

Multiple users may update the same policy.

Example:

User A Updates Policy
User B Updates Policy

Potential conflict.


Version Field

@Version

private Long version;

Hibernate prevents accidental overwrites.


Best Practices

✅ Use repositories for persistence

✅ Keep entities focused on data

✅ Use transactions for business operations

✅ Model relationships carefully

✅ Use optimistic locking

✅ Keep service layer responsible for orchestration


Common Mistakes

❌ Business logic inside entities

❌ Database access inside controllers

❌ Missing transactions

❌ Eager loading everywhere

❌ Exposing entities directly to APIs


Interview Questions

  1. What is JPA?

  2. What is Hibernate?

  3. Difference between JPA and Hibernate?

  4. What is an Entity?

  5. What is JpaRepository?

  6. What is @Transactional?

  7. Difference between @OneToMany and @ManyToOne?

  8. What is optimistic locking?

  9. What is entity lifecycle?

  10. Why use repositories?


Practice Exercises

  1. Create Claim entity.

  2. Create ClaimRepository.

  3. Add PolicyHolder relationship.

  4. Create custom query methods.

  5. Add transaction management.


Key Takeaways

  • JPA is a specification.
  • Hibernate is a JPA implementation.
  • Entities map Java objects to database tables.
  • Repositories simplify database access.
  • Spring Data JPA generates CRUD operations automatically.
  • Relationships model business domains.
  • Transactions ensure data consistency.
  • Persistence is the foundation of enterprise applications.

Chapter Summary

In this chapter, you learned:

  • JPA
  • Hibernate
  • Entity Mapping
  • Repositories
  • CRUD Operations
  • Relationships
  • Transactions
  • Optimistic Locking

Our Insurance Policy Management System can now persist and retrieve data from a database. In the next chapter, we will focus on DTO Mapping, Data Transformation, and API Response Modeling.

Need help with your project?
I can help you explore our services or start an inquiry.