# 業務ロジック — OwnerController.findPaginatedForOwnersLastName() [5 LOC]

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

## 1. 役割

### OwnerController.findPaginatedForOwnersLastName()

本メソッドは、ペットクリニック運営システムにおける「飼い主（Owner）」検索機能の基盤となる、ページネーション対応のデータ取得処理を担当する。ユーザー画面から指定された名前（苗字）の先頭文字列に一致する飼い主レコードをデータベースから抽出し、5件ごとのページ区切りにて結果を返却する。具体的には、1ベースのページ番号をSpring Data JPAが要求する0ベースのインデックスに変換した上で、`Pageable`オブジェクトを構築し、`OwnerRepository`を介してJPAクエリを実行する。このメソッドは画面層の業務ロジック（`processFindForm()`）から呼び出されるプライベートな補助メソッドであり、検索条件の構築とデータベース アクセスの仲介というルーティング／ディスパッチパターンを実装している。システム全体の中では、飼い主情報の検索フローの中間層として位置づけ、検索結果の件数に応じた分岐処理（件数0件のエラー表示、1件の詳細画面リダイレクト、複数件一覧表示）を上位メソッドに提供するためのデータ供給役を務める。

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

```mermaid
flowchart TD
    START(["findPaginatedForOwnersLastName(page, lastname)"])
    STEP1["pageSize = 5"]
    STEP2["PageRequest.of(page - 1, pageSize)"]
    STEP3["owners.findByLastNameStartingWith(lastname, pageable)"]
    END_NODE(["Page<Owner> を返却"])

    START --> STEP1
    STEP1 --> STEP2
    STEP2 --> STEP3
    STEP3 --> END_NODE
```

本メソッドは定数条件分岐を持たない直列処理のみの構成である。ステップは以下の3ステップから成る。

1. ページサイズ `5` の値をローカル定数として割り当てる。
2. Spring Data JPAの `PageRequest` クラスを用いて、0ベースのページインデックスとページサイズを指定した `Pageable` オブジェクトを生成する。
3. 注入された `OwnerRepository` インスタメソッド `findByLastNameStartingWith()` を呼び出し、指定された苗字の先頭一致検索をページネーション付きで実行し、結果の `Page<Owner>` をそのまま返却する。

## 3. パラメータ分析

| No | パラメータ名 | 型 | 業務的説明 |
|----|---------------|------|----------------------|
| 1 | `page` | `int` | 検索結果の一覧表示において、ユーザーが現在閲覧しているページ番号（1ベース）。この値から1を減算して0ベースのページインデックスに変換し、データベースからのレコード取得範囲を制御する。例えば `page=1` の場合、先頭5件（レコード0〜4番目）を取得する。 |
| 2 | `lastname` | `String` | 検索対象の飼い主の姓（ラストネーム）。この文字列の先頭一致にてデータベースを検索し、該当する所有者レコードを抽出する。空文字列やNULLの場合の動作は、下位のRepositoryクエリに委譲される。 |

本メソッドはインスタンストレベルのフィールドを参照しない（`this.owners` はSpring DIコンテナから注入されたリポジトリ参照）。

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

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

| CRUD | SC / CBS | SCコード | エンティティ / DB | 操作の説明 |
|------|----------|---------|-------------|----------------------|
| R | `OwnerRepository.findByLastNameStartingWith` | OwnerRepository | Owner | `OwnerRepository` の `findByLastNameStartingWith` を呼び出し、指定された苗字の先頭一致にて飼い主エンティティをページネーション付きで取得する |

### CRUD詳細

| CRUD | SC / CBS | SCコード | エンティティ / DB | 操作の説明 |
|------|----------|---------|-------------|----------------------|
| R | `findByLastNameStartingWith` | OwnerRepository | `Owner` (DBテーブル: petclinic_owner) | 飼い主の姓の先頭一致検索を実行し、指定されたページ範囲のレコード群を `Page<Owner>` として返却する。内部では JPA の Spring Data クエリジェネレーショングルールに基づき `SELECT * FROM Owner WHERE last_name LIKE ?1%` に相当するクエリが発行される。 |

**分類根拠:**
- 処理種別: `findBy...` という命名パターンから明らかな READ 操作。データベースからのレコード取得のみを行い、書き込みは伴わない。
- エンティティ: `OwnerRepository` は `JpaRepository<Owner, Integer>` を継承しており、操作対象は `Owner` エンティティ（飼い主情報テーブル）。

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

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

| # | 呼び出し元（画面/バッチ） | 呼び出しチェーン（メソッドまでの全経路） | 終端（SC / CRUD / エンティティ） |
|---|----------------------|----------------------------------|-------------------------------|
| 1 | Controller:OwnerController | `OwnerController.processFindForm` -> `OwnerController.findPaginatedForOwnersLastName` | `findByLastNameStartingWith` [R] Owner |  # NOSONAR

### 詳細呼び出しチェーン

| # | 呼び出し元（画面/バッチ） | 呼び出しチェーン（本メソッドまでの全経路） | 終端（SC / CRUD / エンティティ） |
|---|----------------------|--------------------------------------|-------------------------------|
| 1 | Controller:OwnerController | `OwnerController.processFindForm` -> `OwnerController.findPaginatedForOwnersLastName` | `findByLastNameStartingWith` [R] Owner |

**補足:**
- 呼び出し元は `processFindForm()` 単一。本メソッドは `private` メソッドとして定義されており、外部クラスからの直接参照は存在しない。
- `processFindForm()` は Spring MVC の `@PostMapping` アノテーションが付与された検索フォーム送信エンドポイントであり、ユーザーが入力した姓とページ番号を取得して本メソッドを呼び出す。
- 終端のデータベース操作は `OwnerRepository.findByLastNameStartingWith()` による READ のみ。

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

本メソッドには条件分岐（if/else、switch、ループ）が含まれていないため、直列処理を単一ブロックとして記述する。

**ブロック 1** — [PROCESS] `(直列処理)` (L130-L134)

> ページネーション用のページサイズを設定し、Pageableオブジェクトを構築してからRepository呼び出しを実行する。

| # | 種別 | コード |
|---|------|------|
| 1 | SET | `int pageSize = 5;` // ページング件数として5件を固定 |
| 2 | SET | `Pageable pageable = PageRequest.of(page - 1, pageSize);` // 1ベースのpageを0ベースに変換しPageableを構築 |
| 3 | CALL | `owners.findByLastNameStartingWith(lastname, pageable);` // OwnerRepositoryにて姓の先頭一致検索を実行 |
| 4 | RETURN | `return owners.findByLastNameStartingWith(lastname, pageable);` // 検索結果Page<Owner>を呼び出し元に返却 |

## 7. 用語集

| 用語 | 種別 | 業務的意味 |
|------|------|------------------|
| `Owner` | Entity | 飼い主 — ペットクリニックでペットの所有権を保持する人物のドメインエンティティ |
| `lastname` | Parameter | 姓（ラストネーム） — 飼い主検索のキーワードとして使用される苗字 |
| `Page<Owner>` | Return Type | ページネーション結果 — Spring Data JPAが提供するページ単位のレコード集合ラッパ。総件数、総ページ数、現在ページのリストを含む |
| `Pageable` | Interface | ページング情報 — Spring Dataのインターフェース。ページ番号とページサイズを保持し、リポジトリメソッドに渡すことでデータベースのLIMIT/OFFSETを自動生成 |
| `PageRequest` | Class | Spring Data JPAの `Pageable` 実装クラス。0ベースのページインデックスとページサイズを指定してページネーション条件を構築する |
| `findByLastNameStartingWith` | Repository Method | 姓の先頭一致検索メソッド — Spring Data JPAのクエリジェネレーションルールに従い、指定された文字列で始まる姓を持つ Owner を検索する。内部では `LIKE 'prefix%'` に相当するSQLが自動生成される |
| `processFindForm` | Controller Method | 検索フォーム送信ハンドラ — 画面上で入力された姓とページ番号を取得し、本メソッドを呼び出して検索結果を処理する。結果に応じてエラー表示、詳細画面リダイレクト、一覧表示の3パタンに分岐する |
| `@GetMapping` / `@PostMapping` | Annotation | Spring MVCのリクエストマッピングアノテーション — HTTP GET/POSTリクエストを対応するメソッドにルーティングする |
