# Data Access Patterns

## Overview

This codebase uses Spring Data repositories as the primary abstraction for persistent data access. Instead of handwritten DAO classes, the application defines repository interfaces that describe how data should be read and written, and Spring Data generates the implementation details at runtime.

The pattern is consistent across the main domain areas: owners, pet types, and vets. Most access is read-oriented and declarative, with repositories expressing query intent through method names, JPQL annotations, paging types, and caching annotations.

## Implementation Patterns

### Repository interfaces as the main boundary

Data access is modeled as interfaces that extend Spring Data contracts rather than concrete classes.

- [OwnerRepository](src/main/java/org/springframework/samples/petclinic/owner/OwnerRepository.java) extends `JpaRepository`, which provides standard CRUD behavior plus paging and sorting support.
- [PetTypeRepository](src/main/java/org/springframework/samples/petclinic/owner/PetTypeRepository.java) extends `JpaRepository` for the same reason.
- [VetRepository](src/main/java/org/springframework/samples/petclinic/vet/VetRepository.java) extends the lower-level `Repository` interface and declares only the query methods this part of the application needs.

This keeps persistent data concerns close to the domain model while avoiding boilerplate implementation code.

### Query derivation by method name

The owner data access layer relies on Spring Data query derivation:

- [OwnerRepository](src/main/java/org/springframework/samples/petclinic/owner/OwnerRepository.java) defines `findByLastNameStartingWith(...)` to express a prefix search over owner last names.

This is a common pattern in the codebase: the repository method name is the query.

### Explicit queries for ordered lookups

Where the query shape is slightly more specific, the repository uses an explicit JPQL query:

- [PetTypeRepository](src/main/java/org/springframework/samples/petclinic/owner/PetTypeRepository.java) uses `@Query("SELECT ptype FROM PetType ptype ORDER BY ptype.name")`.

This makes the ordering requirement part of the repository contract and keeps callers from needing to sort results themselves.

### Paging for large result sets

Paging is built into repository APIs where the UI or service layer may need to display subsets of data:

- [OwnerRepository](src/main/java/org/springframework/samples/petclinic/owner/OwnerRepository.java) returns `Page<Owner>` for prefix searches.
- [VetRepository](src/main/java/org/springframework/samples/petclinic/vet/VetRepository.java) exposes both `Collection<Vet>` and `Page<Vet>` accessors.

This pattern pushes pagination into the data layer so callers can work with stable, bounded result sets.

### Read optimization with caching

Vet lookups are treated as read-heavy and cached:

- [VetRepository](src/main/java/org/springframework/samples/petclinic/vet/VetRepository.java) marks its read methods with `@Cacheable("vets")`.

The cache sits alongside the repository API, signaling that these results are reused and should not be repeatedly loaded from the database.

### Transactional read semantics

Vet queries are also explicitly marked read-only:

- [VetRepository](src/main/java/org/springframework/samples/petclinic/vet/VetRepository.java) uses `@Transactional(readOnly = true)` on its read methods.

That communicates intent to the persistence layer and helps avoid accidental write behavior in read paths.

## Key Classes

### [OwnerRepository](src/main/java/org/springframework/samples/petclinic/owner/OwnerRepository.java)

Repository for owner persistence access. It combines standard Spring Data JPA CRUD behavior with a derived query for last-name prefix search and an `Optional`-based lookup by id. This is the main example of a repository that leans on Spring Data conventions for most behavior.

### [PetTypeRepository](src/main/java/org/springframework/samples/petclinic/owner/PetTypeRepository.java)

Repository for pet type lookup data. It is intentionally narrow and focused on a single ordered read operation. The explicit JPQL query makes the required sort order part of the repository interface.

### [VetRepository](src/main/java/org/springframework/samples/petclinic/vet/VetRepository.java)

Repository for veterinarian read access. It is optimized for read-heavy usage with read-only transactions, caching, and both collection and paginated access methods. Unlike the JPA repositories, it is declared against Spring Data's base `Repository` abstraction and only exposes the operations needed by the application.

## How It Fits Together

```mermaid
flowchart TD
OwnerRepository["OwnerRepository"] --> JpaRepository["JpaRepository"]
PetTypeRepository["PetTypeRepository"] --> JpaRepository
VetRepository["VetRepository"] --> SpringDataRepository["Spring Data Repository"]
VetRepository --> Cache["Cache vets"]
OwnerRepository --> OwnerQueries["Derived queries and paging"]
PetTypeRepository --> PetTypeQuery["Explicit JPQL query"]
VetRepository --> VetQueries["Read-only cached queries"]
```

The repositories provide the data access surface for the application. Spring Data interprets the interface methods and annotations, generates the backing implementation, and routes calls through JPA, paging, and caching infrastructure as needed.

## Notes for Developers

- Prefer repository interfaces over custom data access classes unless a query cannot be expressed cleanly through Spring Data conventions.
- Use derived query methods when the query intent is obvious from the method name.
- Use `@Query` when ordering or selection logic needs to be explicit and stable.
- Return `Page<T>` when consumers may need pagination; this keeps result sizes manageable.
- Mark read-mostly repository methods as `readOnly = true` when the persistence provider should optimize for reads.
- Add caching only for data that changes infrequently and is expensive or repetitive to load.
- Keep repository APIs narrow. Expose only the operations the application actually needs.

