# 業務ロジック — OwnerController.showOwner() [9 LOC]

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

## 1. 役割

### OwnerController.showOwner()

本メソッドは、ペットクリニック管理システムにおける「飼い主（Owner）詳細画面」のエントリポイントとして機能する。HTTP の GET 要求を `/owners/{ownerId}` パスで受信し、パス変数から抽出された飼い主 ID に基づきデータベースから該当する飼い主のエンティティを取得し、詳細表示用の `ModelAndView` を構築して返す。これは Spring Pet Clinic アプリケーションにおける読み取り専用（Read）の画面表示ロジックであり、データの変更は行わない。

設計パターンとしては、**フロントコントローラーパターンの実現**として Spring MVC の `@GetMapping` アノテーションによって URL ルーティングを宣言し、**デコレートパターン**的に `Optional<Owner>` による安全な検索結果のラップと、失敗時に明確なエラーメッセージを付与した例外スローによって、ドメイン層からコントローラー層へのデータ提供を統一的に扱っている。

本メソッドはシステム全体の larger フローにおいて、飼い主検索画面（`/owners/find`）での検索結果クリックや、飼い主一覧画面からの遷移先として呼び出される終端の画面制御メソッドである。取得した `Owner` オブジェクトは `owners/ownerDetails` ビューテンプレートに渡され、飼い主の基本情報（氏名、住所、都市）、連絡先電話番号、および関連するペット（名前、種類、受診履歴）一覧をユーザーに表示するために使用される。

制御フローは単純直線的である：パラメータ抽出 → データベース検索 → 存在チェック → モデルへの追加 → レスポンス構築。条件分岐は「Owner が存在するか」という単一ブランチのみを持ち、存在しない場合は `IllegalArgumentException` によって処理を停止する。

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

```mermaid
flowchart TD
    START(["/owners/{ownerId} GET 要求受信"])
    START --> EXTRACT["ownerId パスパラメータを抽出"]

    EXTRACT --> FIND["this.owners.findById(ownerId)"]

    FIND --> CHECK{"Owner が存在するか?"}

    CHECK -- "yes" --> ADD["mav.addObject(owner)"]
    CHECK -- "no" --> THROW["IllegalArgumentException をスロー"]

    ADD --> RETURN["ModelAndView を返す"]
    THROW --> END(["リクエスト失敗"])

    RETURN --> END
```

## 3. パラメータ分析

| No | パラメータ名 | 型 | 業務的説明 |
|----|---------------|------|---------------------|
| 1 | `ownerId` | `@PathVariable("ownerId") int` | 表示対象の飼い主を一意に特定する整数 ID。HTTP リクエストの URL パス（例: `/owners/1`）から抽出され、オーナー検索画面での選択結果や、飼い主一覧画面からの遷移時に付与される。この ID に対応する飼い主レコードが存在しない場合、例外によりリクエストは中止される。有効値はデータベースの `owners` テーブルの主キー値（正の整数）。 |
| — | `this.owners` | `OwnerRepository` | コントローラーのコンストラクターインジェクションにより注入された Spring Data JPA リポジトリ。`JpaRepository<Owner, Integer>` を実装しており、`findById(Integer)` メソッドを通じて `owners` テーブルに対する読み取り操作を実行する。 |

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

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

| CRUD | SC / CBS | SCコード | エンティティ / DB | 操作の説明 |
|------|----------|---------|-------------|----------------------|
| R | `OwnerRepository.findById` | (なし — Spring Data JPA 生成) | `owners` (Entity: `Owner`) | `OwnerRepository` の `findById(Integer id)` を呼び出し、指定 ID に一致する飼い主エンティティをデータベースから検索する。`Optional<Owner>` として返される。 |

**CRUD 分類の詳細：**

| CRUD | SC / CBS | SCコード | エンティティ / DB | 操作の説明 |
|------|----------|---------|-------------|----------------------|
| R | `OwnerRepository.findById` | (Spring Data JPA 自動生成) | `owners` (`Owner`) | コントローラーが注入した `OwnerRepository` の `findById` メソッドを呼び出し、`ownerId` に一致する飼い主レコードを `owners` テーブルから読み取る。存在しない場合は空の `Optional` が返され、後の `orElseThrow` によって例外が発生する。 |

**分類根拠：**
- **R (Read)**: `findById` という命名は明確に検索操作を示す。`OwnerRepository` は `JpaRepository<Owner, Integer>` を実装しており、内部で対応する主キーによる SELECT クエリを発行する。データの変更（INSERT/UPDATE/DELETE）は行われない。

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

本メソッドは `@GetMapping("/owners/{ownerId}")` アノテーションによって Spring MVC フレームワークから直接呼び出される画面エントリポイントである。したがって、Java コード上での直接的な呼び出し元は存在せず、HTTP リクエスト経由で呼び出される。

| # | 呼び出し元（画面/バッチ） | 呼び出しチェーン（本メソッドまでの全経路） | 終端（SC / CRUD / エンティティ） |
|---|----------------------|--------------------------------------|-------------------------------|
| 1 | 画面: Owner 詳細表示 | `GET /owners/{ownerId}` → `DispatcherServlet` → `OwnerController.showOwner(ownerId)` | `OwnerRepository.findById` [R] `owners` (`Owner`) |

**補足：**
- 他の Controller メソッド（`initFindForm`, `processCreationForm`, `processUpdateForm` など）は本メソッドを直接呼び出さない。
- 関連する呼び出し元として、`processCreationForm` および `processUpdateForm` はレスポンスとして `redirect:/owners/{ownerId}` を返すことで、本メソッドの動作を間接的にトリガーする（新規作成・編集完了後のリダイレクト先）。

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

**ブロック 1** — [GET リクエストハンドラー] `(condition: @GetMapping("/owners/{ownerId}"))` (L167)

> HTTP GET 要求 `/owners/{ownerId}` を受信し、ownerId パラメータを抽出する。

| # | 種別 | コード |
|---|------|------|
| 1 | ANNOT | `@GetMapping("/owners/{ownerId}")` |
| 2 | ANNOT | `@PathVariable("ownerId") int ownerId` — URL パスから飼い主 ID を抽出 |

**ブロック 2** — [処理: ModelAndView の初期化] (L168)

> 表示対象のビュー（`owners/ownerDetails`）を指定した ModelAndView オブジェクトを作成する。

| # | 種別 | コード |
|---|------|------|
| 1 | SET | `ModelAndView mav = new ModelAndView("owners/ownerDetails")` — 詳細表示用ビューの名前を設定 |

**ブロック 3** — [処理: データベース検索] (L169)

> `OwnerRepository.findById()` を呼び出し、指定 ID の飼い主レコードをデータベースから取得する。検索結果は `Optional<Owner>` としてラップされる。

| # | 種別 | コード |
|---|------|------|
| 1 | CALL | `this.owners.findById(ownerId)` — `OwnerRepository.findById(Integer)` を呼び出す |
| 2 | SET | `Optional<Owner> optionalOwner = this.owners.findById(ownerId)` — 検索結果を Optional に格納 |

**ブロック 4** — [処理: 存在チェックと所有者取得] (L170-L171)

> Optional から Owner をアンラップ。存在しない場合は `IllegalArgumentException` をスローして処理を中止する。

| # | 種別 | コード |
|---|------|------|
| 1 | CALL | `optionalOwner.orElseThrow(...)` — 空の Optional の場合は例外スロー |
| 2 | SET | `Owner owner = optionalOwner.orElseThrow(...)` — 飼い主オブジェクトを取得 |
| 3 | EXEC | 例外メッセージ生成: `"Owner not found with id: " + ownerId` — エラーメッセージに ID を埋め込み |

**ブロック 5** — [処理: モデルへの属性追加] (L172)

> 取得した Owner オブジェクトを ModelAndView のモデル属性として追加し、ビューが参照可能にする。

| # | 種別 | コード |
|---|------|------|
| 1 | EXEC | `mav.addObject(owner)` — Owner オブジェクトをモデルに追加 |

**ブロック 6** — [処理: レスポンス返却] (L173)

> 構築済みの ModelAndView を呼び出し元（DispatcherServlet）に返す。フレームワークが `owners/ownerDetails` ビューをレンダリングし、HTML レスポンスを生成する。

| # | 種別 | コード |
|---|------|------|
| 1 | RETURN | `return mav` — ModelAndView を返す |

## 7. 用語集

| 用語 | 種別 | 業務的意味 |
|------|------|------------------|
| `Owner` | Entity | 飼い主 — ペットクリニックにおけるペットの所有者（顧客）を表すドメインエンティティ。名前、住所、都市、電話番号を保持し、複数のペット（Pet）と紐づく。 |
| `Pet` | Entity | ペット — 飼い主に紐づく動物の情報。名前、種類（PetType）、生年月日、受診履歴（Visit）を含む。 |
| `Visit` | Entity | 受診 — ペットの獣医診察記録。日付、概要、金額などの情報を保持する。 |
| `OwnerRepository` | Interface | 飼い主リポジトリ — Spring Data JPA による `Owner` エンティティの永続化を担うインターフェース。`JpaRepository<Owner, Integer>` を実装。 |
| `findById` | Method | 主キーによる検索 — `OwnerRepository` が提供する、整数 ID で飼い主を検索するメソッド。`Optional<Owner>` を返す。 |
| `ModelAndView` | Class | Spring MVC のレスポンス型 — ビュー名とモデル（属性データ）を保持し、コントローラーからビューレンダリングへ渡す。 |
| `@GetMapping` | Annotation | Spring MVC の HTTP GET マッピング注釈 — 指定パスの GET 要求を該当メソッドにルーティングする。 |
| `@PathVariable` | Annotation | URL パスパラメータのバインド注釈 — `/owners/{ownerId}` における `{ownerId}` の値をメソッドパラメータに抽出する。 |
| `Optional` | Class | Java の null 安全ラッパークラス — 存在するかも存在しないかも値をラップし、`orElseThrow` による明示的なエラー処理を可能にする。 |
| `IllegalArgumentException` | Exception | 不正引数例外 — ownerId に対応するOwnerが見つからなかった場合にスローされ、クライアントにエラーレスポンスを返す。 |
| `owners` | テーブル名 | 飼い主情報格納テーブル — JPA `@Table(name = "owners")` によりマッピングされる。主キー、氏名、住所、都市、電話番号を保持する。 |
| `owners/ownerDetails` | ビュー名 | 飼い主詳細表示用の Thymeleaf / JSP ビーテンプレート名。 |
| `JpaRepository` | Interface | Spring Data JPA の基本リポジトリインターフェース — `findById`, `save`, `delete` などの標準 CRUD 操作を提供する。 |
