# Data Access Patterns

## Overview

This codebase uses Spring Data repositories as the primary abstraction for reading and writing persistent data. Rather than implementing data-access logic in service classes, the application defines repository interfaces that describe the needed queries and let Spring Data provide the implementation at runtime.

Across the repository layer, the main goals are:

- keep persistence concerns close to the domain model,
- express common lookups through repository method names,
- use explicit queries only when the default derivation is not enough,
- and cache frequently read reference data where it improves performance.

## Implementation Patterns

### 1. Repository interfaces define the persistence boundary

The codebase relies on Spring Data repository interfaces instead of handwritten DAO implementations. These interfaces are small, focused, and domain-oriented.

- [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)

### 2. Standard CRUD support comes from Spring Data

`OwnerRepository` and `PetTypeRepository` extend `JpaRepository`, which provides the usual persistence operations such as saving, loading, and deleting entities, along with paging and sorting support where applicable.

`VetRepository` extends Spring Data's more minimal `Repository` marker interface, indicating that only selected read methods are exposed. This is a deliberate pattern when a repository should present a narrow API instead of the full CRUD surface.

### 3. Query derivation handles common lookups

`OwnerRepository` uses a derived query method:

- `findByLastNameStartingWith(...)`

Spring Data interprets the method name and generates the query automatically. This keeps the repository interface readable while still supporting common search behavior.

### 4. Explicit JPQL is used for ordered reference data

`PetTypeRepository` uses an explicit `@Query` annotation for `findPetTypes()`. The query returns pet types ordered by name, which is useful for UI lists and other reference-data lookups where stable ordering matters.

### 5. Read-heavy lookups are cached

`VetRepository` marks both `findAll()` variants with `@Cacheable("vets")`. This indicates that vet data is expected to be read often and change relatively infrequently. Caching reduces repeated database hits for the same result set.

### 6. Read-only semantics are expressed declaratively

`VetRepository` also marks its read methods with `@Transactional(readOnly = true)`. This signals that the methods do not modify state and allows the persistence provider to optimize accordingly.

## Key Classes

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

Repository for owner records. It combines `JpaRepository` inheritance with a derived query for last-name searches and an explicit `findById(...)` contract that returns `Optional<Owner>`.

Why it matters:

- supports the main owner lookup flows,
- shows the standard pattern for paged queries,
- and demonstrates how repository interfaces can declare domain-specific search behavior without implementation classes.

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

Repository for pet type reference data. It extends `JpaRepository` and defines a dedicated query that returns all pet types ordered by name.

Why it matters:

- provides stable ordering for dropdowns and forms,
- centralizes a small but important reference-data query,
- and shows when an explicit query is preferable to a derived method name.

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

Repository for vet records. It exposes only read methods through the Spring Data `Repository` interface, and it applies caching and read-only transactions to those lookups.

Why it matters:

- represents the read-optimized side of the data-access layer,
- avoids exposing unnecessary write operations,
- and demonstrates how the codebase combines Spring Data with caching for hot reference data.

## How It Fits Together

```mermaid
flowchart TD
OwnerRepo["OwnerRepository"] --> JpaRepo["JpaRepository"]
PetTypeRepo["PetTypeRepository"] --> JpaRepo
VetRepo["VetRepository"] --> SpringRepo["Spring Data Repository"]
VetRepo --> Cache["Cache vets"]
OwnerRepo --> QueryMethods["Derived query methods"]
PetTypeRepo --> QueryAnnotation["@Query"]
```

In practice, the flow is:

1. Application code depends on repository interfaces.
2. Spring Data generates the implementation at runtime.
3. Derived query names and explicit JPQL define the actual database access.
4. Frequently used read paths can be cached.
5. Transactional hints mark read-only operations where appropriate.

## Notes for Developers

- Prefer repository interfaces over custom persistence classes unless the query truly needs bespoke behavior.
- Use method-name derivation for straightforward lookups, especially when the query expresses itself clearly in the method name.
- Use `@Query` when ordering, joins, projections, or other details would make derivation awkward.
- Consider caching for read-heavy, slowly changing reference data such as vet lists.
- Keep repository interfaces narrow: exposing only the operations a feature needs makes the persistence boundary easier to reason about.
- Preserve `Optional`-based lookups for single-entity fetches where absence is a normal outcome.
- When adding new repository methods, follow the existing style of small interfaces and clear domain naming.
