# 業務ロジック — Owner.toString() [11 LOC]

| 項目 | 値 |
|-------|-------|
| 完全修飾名 | `org.springframework.samples.petclinic.owner.Owner` |
| レイヤー | Utility（ドメインモデル） |
| モジュール | `owner`（パッケージ: `org.springframework.samples.petclinic.owner`）

## 1. 役割

### Owner.toString()

本メソッドは、Spring Pet Clinic アプリケーションにおける「ペットオーナー」实体のデバッグ用文字列表現を生成するための標準 Java `toString()` メソッドのオーバーライドです。Spring が提供する `ToStringCreator` を使用し、オーナーの主要属性を一括で文字列にまとめることで、ロギングやデバッグ時の可読性を高めます。

このメソッドが出力する情報は、オーナーを一意に特定するための識別子（`id`）、新規登録フラグ（`new`）、氏名（`lastName`、`firstName`）、住所（`address`）、都市名（`city`）、電話番号（`telephone`）の 7 つです。これらは Spring Pet Clinic ドメインモデルの中心的存在である Owner エンティティの全必須フィールドを網羅しており、システム全体の状態監視やエラー調査においてオーナー情報を即座に把握するための基盤となる情報源です。

本メソッドは条件分岐や複雑な業務ロジックを持たない純粋なデータ変換メソッドであり、特定のサービスタイプやカテゴリに依存しません。システム全体のあらゆるレイヤー（Controller、Service、Repository）から参照可能な汎用ユーティリティメソッドとして振る舞い、オブジェクトの現在の状態をシリアライズされた形式で出力する役割を担います。設計パターンとしては、Java の標準的な Object オブジェクト契約（`Object.toString()`）に従ったデコレータ的な振る舞いを実装しています。

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

```mermaid
flowchart TD
    START(["toString()"])
    START --> CREATE["ToStringCreator インスタンス生成"]
    CREATE --> A1["append id getId"]
    A1 --> A2["append new isNew"]
    A2 --> A3["append lastName getLastName"]
    A3 --> A4["append firstName getFirstName"]
    A4 --> A5["append address address"]
    A5 --> A6["append city city"]
    A6 --> A7["append telephone telephone"]
    A7 --> FINAL["toString 呼び出し"]
    FINAL --> RESULT(["String 返却"])
```

本メソッドは逐次的な処理フローのみで構成され、条件分岐やループは存在しません。以下の順序で処理が実行されます。

1. `START` — `toString()` 呼び出し
2. `ToStringCreator` のインスタンス生成 — `this` 参照を渡して自身を表すビルダーを初期化
3. 各フィールド値の `append` 呼び出しを 7 回連続実行
4. 最終的に `toString()` を呼び出し、ビルドされた文字列を返却

## 3. パラメータ分析

| No | パラメータ名 | 型 | 業務的説明 |
|----|---------------|------|---------------------|
| - | (なし) | - | - |

### 参照するインスタンスフィールド・外部状態

| 対象 | 型 | 業務的説明 |
|------|------|---------------------|
| `this.getId()` | `Integer` | オーナーのデータベース上での主キー。`BaseEntity` から継承。NULL の場合は新規登録済みでない状態を示す |
| `this.isNew()` | `boolean` | オーナーが未保存の新規エンティティかどうかを示すフラグ。`BaseEntity` から継承。`id` が NULL の場合に `true` |
| `this.getLastName()` | `String` | オーナーの苗字。`Person` から継承。必須項目（`@NotBlank`） |
| `this.getFirstName()` | `String` | オーナーの名前。`Person` から継承。必須項目（`@NotBlank`） |
| `this.address` | `String` | オーナーの住所。直接参照（ゲッター経由ではなくフィールドアクセス）。必須項目（`@NotBlank`） |
| `this.city` | `String` | オーナーの都市名。直接参照（ゲッター経由ではなくフィールドアクセス）。必須項目（`@NotBlank`） |
| `this.telephone` | `String` | オーナーの電話番号。直接参照（ゲッター経由ではなくフィールドアクセス）。必須項目（`@NotBlank`）、10 桁の数字（`@Pattern(regexp = "\d{10}")`） |

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

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

| CRUD | SC / CBS | SCコード | エンティティ / DB | 操作の説明 |
|------|----------|---------|-------------|----------------------|
| R | `BaseEntity.getId` | BaseEntity | - | `BaseEntity` クラスの `getId()` を呼び出し、オーナーの主キー ID を取得 |
| R | `BaseEntity.isNew` | BaseEntity | - | `BaseEntity` クラスの `isNew()` を呼び出し、新規登録フラグを取得 |
| R | `Person.getFirstName` | Person | - | `Person` クラスの `getFirstName()` を呼び出し、オーナーの名前を取得 |
| R | `Person.getLastName` | Person | - | `Person` クラスの `getLastName()` を呼び出し、オーナーの苗字を取得 |

### CRUD 操作まとめ

| CRUD | SC / CBS | SCコード | エンティティ / DB | 操作の説明 |
|------|----------|---------|-------------|----------------------|
| R | `getId` | - | `owners.id` | オーナーエンティティの主キー（ID）を参照。データベース `owners` テーブルのレコード識別子 |
| R | `isNew` | - | - | オーナーエンティティが新規状態かどうかの判定フラグを取得 |
| R | `getLastName` | - | `owners.last_name` | オーナーの苗字情報を参照。`Person` 基底クラスから継承したフィールド |
| R | `getFirstName` | - | `owners.first_name` | オーナーの名前情報を参照。`Person` 基底クラスから継承したフィールド |
| R | `address` | - | `owners.address` | オーナーの住所情報を直接フィールドアクセスで参照 |
| R | `city` | - | `owners.city` | オーナーの都市名情報を直接フィールドアクセスで参照 |
| R | `telephone` | - | `owners.telephone` | オーナーの電話番号情報を直接フィールドアクセスで参照 |

本メソッドはデータベースへの書き込み（C/U/D）を一切行わず、すべて読み取り（R）操作のみで構成されます。JPA エンティティの状態を文字列としてシリアライズするだけの純粋な表示用メソッドです。

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

本メソッド `toString()` は Java の標準契約によるメソッドであり、意図的に呼び出すケースは限定的ですが、主に以下のようなシーンで間接的に参照されます。

| # | 呼び出し元（画面/バッチ） | 呼び出しチェーン（本メソッドまでの全経路） | 終端（SC / CRUD / エンティティ） |
|---|----------------------|--------------------------------------|-------------------------------|
| 1 | 間接呼び出し（ロギングフレームワーク） | `logger.debug(owner)` -> `String.valueOf(owner)` -> `Owner.toString` | `getId [R] owners.id` |
| 2 | 間接呼び出し（デバッグ出力） | `System.out.println(owner)` -> `Owner.toString` | `getFirstName [R] owners.first_name` |
| 3 | 間接呼び出し（Spring デバッグログ） | `OwnerController.findOwner` -> ロギング -> `Owner.toString` | `getLastName [R] owners.last_name` |
| 4 | 間接呼び出し（Spring Data JPA） | `OwnerRepository.findById(ownerId)` -> 検索結果の `toString` | `address [R] owners.address` |
| 5 | 間接呼び出し（Spring MVC リクエスト） | `PetController.findOwner(@PathVariable("ownerId"))` -> 例外メッセージ組み立て -> `Owner.toString` | `telephone [R] owners.telephone` |

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

本メソッドには条件分岐（if/else、switch/case、ループ）が存在しません。処理は完全な逐次フローであり、以下のようなブロック構造になります。

**ブロック 1** — [ sequential processing ] (L148)

> `ToStringCreator` を使用した文字列表現のビルド処理。条件分岐なしで 7 つのフィールドを順次 append する。

| # | 種別 | コード |
|---|------|------|
| 1 | EXEC | `new ToStringCreator(this)` — `this` 参照を渡して ToStringCreator インスタンスを生成 |
| 2 | EXEC | `.append("id", this.getId())` — オーナーの主キー ID をキー "id" で追加 |
| 3 | EXEC | `.append("new", this.isNew())` — 新規登録フラグをキー "new" で追加 |
| 4 | EXEC | `.append("lastName", this.getLastName())` — 苗字をキー "lastName" で追加 |
| 5 | EXEC | `.append("firstName", this.getFirstName())` — 名前をキー "firstName" で追加 |
| 6 | EXEC | `.append("address", this.address)` — 住所をキー "address" で追加 |
| 7 | EXEC | `.append("city", this.city)` — 都市名をキー "city" で追加 |
| 8 | EXEC | `.append("telephone", this.telephone)` — 電話番号をキー "telephone" で追加 |

**ブロック 2** — [ RETURN ] (L155)

> `toString()` 呼び出しにより、ビルドされた文字列を返却する。

| # | 種別 | コード |
|---|------|------|
| 1 | RETURN | `.toString();` — 文字列表現を返す |

## 7. 用語集

| 用語 | 種別 | 業務的意味 |
|------|------|------------------|
| `Owner` | Class | ペットオーナーエンティティ。`Person` を継承し、住所・都市名・電話番号・ペット一覧を保有する JPA エンティティ |
| `Person` | Class | 氏名（firstName, lastName）を保有する `Owner` と `Veterinarian` の共通基底クラス。`@MappedSuperclass` |
| `BaseEntity` | Class | 全 JPA エンティティの共通基底クラス。主キー `id` と新規判定メソッド `isNew()` を提供 |
| `ToStringCreator` | Class | Spring Core が提供するユーティリティクラス。`Object.toString()` の簡易実装を支援 |
| `owners` | Table | ペットオーナー情報を保持する JPA テーブル。`@Table(name = "owners")` でマッピング |
| `id` | Field | オーナーの主キー。`GenerationType.IDENTITY` により自動採番。NULL の場合は新規レコード |
| `address` | Field | オーナーの住所。必須項目（`@NotBlank`） |
| `city` | Field | オーナーの都市名。必須項目（`@NotBlank`） |
| `telephone` | Field | オーナーの電話番号。10 桁の数字に制限（`@Pattern(regexp = "\d{10}")`） |
| `firstName` | Field | オーナーの名前。`Person` クラスで定義。必須項目（`@NotBlank`） |
| `lastName` | Field | オーナーの苗字。`Person` クラスで定義。必須項目（`@NotBlank`） |
| `pets` | Field | オーナーが所有するペットの一覧。`@OneToMany` 関係。`CascadeType.ALL` で連携制御 |
| `isNew()` | Method | オーナーエンティティが未保存状態かどうかを判定。`id` が NULL の場合に `true` を返す |
| Spring Pet Clinic | Application | Spring Framework のサンプルアプリケーション。動物病院の顧客・ペット・診察記録を管理するシステム |
| JPA | Technology | Java Persistence API。Java オブジェクトとリレーショナルデータベースのマッピング仕様 |
| `@MappedSuperclass` | Annotation | 継承元クラスのマッピング情報をサブクラスに継承させる JPA アノテーション |
