# 業務ロジック — OwnerController.findOwner() [7 LOC]

| 項目 | 値 |
|-------|-------|
| 完全修飾名 | `org.springframework.samples.petclinic.owner.OwnerController` |
| レイヤー | Controller（Spring MVC `@Controller`） |
| モジュール | `owner`（パッケージ: `org.springframework.samples.petclinic.owner`）

## 1. 役割

### OwnerController.findOwner()

このメソッドは、Spring Clinic アプリケーションの「オーナー（ペット所有者）」管理ドメインにおける **モデル属性の初期化** を担う Spring MVC コントローラのライフサイクルメソッドです。`@ModelAttribute("owner")` アノテーションを付与されているため、このコントローラが属するリクエスト処理の直前に **自動的に呼び出され**、URL パスの `ownerId` に該当するオーナー情報をデータベースから取得してモデルに格納します。

業務的な操作としては、**オーナー情報の検索（読み取り）** に該当します。具体的には、URL から抽出された `ownerId` をキーとして `OwnerRepository.findById()` を介してデータベース上のオーナーレコードを取得し、存在すれば対応する `Owner` エンティティを返します。存在しない場合は、`IllegalArgumentException` をスローして処理を異常終了させます。ただし、`ownerId` が `null` の場合は、空の `Owner` インスタンスを新規作成して返すことで、新規作成画面の初期表示を可能にします。

このメソッドが実装するデザインパターンは **ブートストラップ（初期化）パターン** および **委譲パターン** です。自身ではデータベースアクセスを行わず、`OwnerRepository` への委譲によって関心の分離（Separation of Concerns）を実現しています。また、システム全体では **共有の初期化ファサード** としての役割を果たしており、`OwnerController` だけでなく `PetController` や `VisitController` といった他のコントローラでも同様のメカニズムで利用されています。

条件分岐として、以下の2つのブランチを持ちます：

1. **ownerId が null の場合（新規作成ブランチ）**：空の `Owner` オブジェクトを生成して返す。新規オーナー作成画面の初期表示で使用される。
2. **ownerId が存在する場合（既存オーナー検索ブランチ）**：`OwnerRepository.findById()` でデータを取得し、存在チェック後に返す。オーナー詳細表示・編集画面で使用される。

## 2. 処理パターン（詳細業務ロジック）

```mermaid
flowchart TD
    START(["findOwner params"])
    COND["ownerId == null?"]
    NULL_BRANCH["new Owner()"]
    NOT_NULL["owners.findById(ownerId)"]
    OPT_EMPTY{Optional isEmpty?}
    THROW["throw IllegalArgumentException"]
    RETURN(["return Owner"])

    START --> COND
    COND -->|true| NULL_BRANCH
    COND -->|false| NOT_NULL
    NOT_NULL --> OPT_EMPTY
    OPT_EMPTY -->|true| THROW
    OPT_EMPTY -->|false| RETURN
    THROW --> RETURN
    NULL_BRANCH --> RETURN
```

## 3. パラメータ分析

| No | パラメータ名 | 型 | 業務的説明 |
|------|---------------|------|---------------------|
| 1 | `ownerId` | `@PathVariable(name = "ownerId", required = false) Integer` | ペット所有者の一意識別子。URL パスから抽出され、既存オーナー情報の検索キーとして使用される。`null` の場合は新規オーナー作成時の空オブジェクト生成トリガとなる。正の整数を想定。 |

- **instance fields**: `private final OwnerRepository owners` — Spring Data JPA によって実装されたオーナーデータアクセス層。注入済みのリポジトリインスタンス経由でデータベースとの対話を委譲する。

## 4. CRUD操作／呼び出しサービス

### コード解析グラフからの事前抽出エビデンス:

| CRUD | SC / CBS | SCコード | エンティティ / DB | 操作の説明 |
|------|----------|---------|-------------|----------------------|
| R | `OwnerRepository.findById` | OwnerRepository | `Owner`（`owners` テーブル） | `findById(Integer)` でオーナーエンティティを取得。`Optional<Owner>` を返す。 |

このメソッドは **読み取り（R）のみ** を実行する。`OwnerRepository.findById()` を呼び出し、結果を `Optional<Owner>` として返す。該当レコードが存在しない場合、`Optional.isEmpty()` の結果に応じて `IllegalArgumentException` をスローして異常終了させる。

## 5. 依存関係トレース

このメソッドは `@ModelAttribute` アノテーションを付与されたメソッドであり、通常の Java メソッド呼び出しチェーンではなく **Spring MVC のリクエスト処理パイプライン** から自動的に呼び出される。具体的には、このコントローラ内の任意のハンドラーメソッド (`@GetMapping` / `@PostMapping`) が実行される前に Spring フレームワークによって自動呼び出される。

| # | 呼び出し元（画面/バッチ） | 呼び出しチェーン（本メソッドまでの全経路） | 終端（SC / CRUD / エンティティ） |
|---|----------------------|--------------------------------------|-------------------------------|
| 1 | Controller:OwnerController | Spring MVC リクエストディスパッチャ → `OwnerController.findOwner` | `OwnerRepository.findById [R] owners` |
| 2 | Controller:PetController | Spring MVC リクエストディスパッチャ → `PetController` の `@ModelAttribute("owner")` → `OwnerController.findOwner` | `OwnerRepository.findById [R] owners` |
| 3 | Controller:VisitController | Spring MVC リクエストディスパッチャ → `VisitController` の `@ModelAttribute("owner")` → `OwnerController.findOwner` | `OwnerRepository.findById [R] owners` |

※ `PetController` および `VisitController` は同じ `owner` パッケージに属し、それぞれ `@ModelAttribute("owner")` で同様のオーナー初期化を宣言している。

## 6. 分岐ごとの詳細ブロック

**ブロック 1** — IF `(ownerId == null)` (L65)

> `ownerId` が `null` の場合、新規オーナー作成用の空オブジェクトを生成して返す。新規オーナー作成画面の初期表示や、ID が未指定のリクエストに対応する。

| # | 種別 | コード |
|---|------|------|
| 1 | RETURN | `return new Owner()` |

**ブロック 2** — ELSE `(ownerId != null)` (L66)

> `ownerId` が指定されている場合、`OwnerRepository.findById()` を介してデータベースから該当オーナーを検索する。

| # | 種別 | コード |
|---|------|------|
| 1 | CALL | `this.owners.findById(ownerId)` |
| 2 | SET | `Optional<Owner> result = findById(ownerId)` // リポジトリからエンティティを取得 |

**ブロック 2.1** — IF-ELSE-IN-LINE `(Optional.isEmpty())` (L67)

> 検索結果の `Optional` が空（該当レコードなし）の場合、業務例外をスローする。

| # | 種別 | コード |
|---|------|------|
| 1 | EXEC | `orElseThrow(() -> new IllegalArgumentException("Owner not found with id: " + ownerId + ". Please ensure the ID is correct " + "and the owner exists in the database."))` |
| 2 | RETURN | `throw IllegalArgumentException` // 異常終了：オーナー未発見 |

**ブロック 2.2** — ELSE `(Optional.isPresent())` (L67)

> 検索結果が存在する場合、該当の `Owner` エンティティを返す。

| # | 種別 | コード |
|---|------|------|
| 1 | RETURN | `return Optional.get()` // 取得した Owner エンティティを返す |

## 7. 用語集

| 用語 | 種別 | 業務的意味 |
|------|------|------------------|
| `Owner` | Entity | ペット所有者（オーナー）エンティティ。飼い主の個人情報を管理するドメインモデル |
| `ownerId` | Field / PathVariable | オーナー一意識別子。URL パラメータとして付与され、DB 検索のキーとなる |
| `OwnerRepository` | Interface | Spring Data JPA リポジトリインターフェース。`Owner` エンティティの永続化を管理する |
| `findById` | Method | 主キーによるエンティティ取得メソッド。`Optional<T>` を返す |
| `@ModelAttribute` | Annotation | Spring MVC のアノテーション。コントローラメソッドの実行前にモデル属性を初期化するために自動呼び出される |
| `@PathVariable` | Annotation | URL パスのプレースホルダにマップされた値を取得するための Spring MVC アノテーション |
| `IllegalArgumentException` | Exception | 不正な引数が渡された場合にスローされるランタイム例外。本メソッドではオーナー未発見時のエラーメッセージとして使用 |
| `Optional` | Type | Java 8 の null 安全ラッパークラス。`isEmpty()` で存在チェックを行い、`orElseThrow()` で未発見時の例外送出を記述する |
| `Spring Data JPA` | Technology | Spring Framework の JPA サポート。リポジトリパターンによるデータベースアクセスの抽象化を提供する |
