# Data Access Patterns

## Overview

This codebase uses Spring Data repository interfaces as the primary boundary for reading and writing persistent data. The repositories are intentionally small and declarative: they describe *what* data should be retrieved, while Spring Data JPA provides the implementation details for SQL generation, entity mapping, and transaction integration.

In practice, the persistence model centers on three repository types:
- `OwnerRepository` for owner lookup and paging
- `PetTypeRepository` for the shared catalog of pet types
- `VetRepository` for vet read access with caching

This approach keeps data access consistent across the application and makes persistence behavior easy to reason about from the repository layer alone.

## Implementation Patterns

### Repository interfaces instead of concrete DAOs

The codebase relies on Spring Data interfaces rather than hand-written DAO classes. That means the repository definition itself is the contract, and Spring generates the runtime implementation.

- [OwnerRepository](src/main/java/org/springframework/samples/petclinic/owner/OwnerRepository.java)
- [PetTypeRepository](src/main/java/org/springframework/samples/petclinic/owner/PetTypeRepository.java)
- [VetRepository](src/main/java/org/springframework/samples/petclinic/vet/VetRepository.java)

### CRUD and query derivation from method names

`OwnerRepository` extends `JpaRepository`, which provides standard CRUD behavior and paging support. It also defines a derived query method, `findByLastNameStartingWith(...)`, showing the common pattern of expressing searches directly in the method name instead of writing explicit query code.

This pattern matters because it keeps simple lookups compact and readable, while still allowing the framework to generate the actual query.

### Explicit queries for ordered lookups

`PetTypeRepository` also extends `JpaRepository`, but it adds a JPQL query with `@Query` to control the result ordering.

This indicates a second pattern used in the codebase:
- use derived queries when the method name is expressive enough
- use explicit JPQL when the query needs deterministic behavior such as ordering

### Read-only repository views for cached reference data

`VetRepository` uses the narrower Spring Data `Repository` interface instead of `JpaRepository`. That signals a deliberate read-focused boundary rather than a full CRUD surface.

The interface also applies:
- `@Transactional(readOnly = true)` to make intent explicit
- `@Cacheable("vets")` to cache vet listings
- pageable and non-pageable `findAll(...)` methods for flexible read access

This is the clearest example of the codebase optimizing a read-heavy path with caching while keeping the repository API small.

## Key Classes

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

Repository for the owner domain model. It represents the main pattern for entity access in this area of the codebase:
- inherits standard persistence operations from Spring Data JPA
- supports paged retrieval
- supports name-based lookup through query derivation

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

Repository for reference data describing pet types. It demonstrates explicit JPQL for a stable, ordered list of types, which is useful when the UI or other callers expect a predictable presentation order.

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

Repository for vet read operations. It is intentionally narrower than a full JPA repository and emphasizes performance-oriented read access:
- read-only transactions
- caching for repeated requests
- paged and unpaged retrieval variants

## How It Fits Together

```mermaid
flowchart TD
A["Application services and controllers"] --> B["OwnerRepository"]
A --> C["PetTypeRepository"]
A --> D["VetRepository"]
B --> E["Spring Data JPA"]
C --> E
D --> F["Spring Data repository infrastructure"]
D --> G["Cache vets"]
E --> H["Persistent data store"]
F --> H
```

The flow is straightforward:
1. Higher-level application code calls a repository interface.
2. Spring Data interprets the interface, method names, and annotations.
3. The framework executes the underlying data access logic against the persistent store.
4. For vet reads, results can be served from the `vets` cache instead of hitting the store every time.

## Notes for Developers

- Prefer repository interfaces over custom data-access classes when the need is simple enough for Spring Data conventions.
- Use derived query methods for straightforward lookups that map cleanly to method names.
- Use `@Query` when ordering, filtering, or query shape needs to be explicit.
- Keep read-heavy reference data paths cacheable when repeated requests are expected.
- Use `@Transactional(readOnly = true)` on repository methods that only read data, especially when combining with caching or paging.
- Choose the narrowest repository base interface that matches the use case; `Repository` can be enough when you want to expose only specific reads.
- When adding new repositories, follow the same pattern of small, declarative interfaces so persistence concerns stay centralized and easy to scan.
