# 業務ロジック — Owner.addPet() [5 LOC]

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

## 1. 役割

### Owner.addPet()

`Owner.addPet()` メソッドは、ペットクリニック管理システムにおける「飼い主（Owner）と飼育動物（Pet）の関連付け」を行うドメイン層の操作メソッドである。業務的には、新たに登録された動物（Pet）を特定の飼い主（Owner）の所有リストに追加する処理を担う。本メソッドは、引数で受け取った Pet オブジェクトが新規登録対象かどうかを `pet.isNew()` によって判定し、新規であれば Owner が保持する `pets` コレクション（データベースの `owners` テーブルと `pets` テーブル間の 1 対多リレーションの対応集合）に追加する。一方、既に ID を持つ既存の動物については何もしないため、二重登録や予期せぬ関連付けを防ぐガード節としての役割も果たす。

設計パターンとしては、ドメインモデルパターンのエンティティ間関連付けに該当する。Owner エンティティが自らの子集合（pets）を管理し、外部からの追加リクエストを内部集合への挿入として実行する単純な委譲構造を採用している。本メソッドは単一の Owner インスタンスに対して動作するため、バッチ処理や大規模なデータ操作を行うものではなく、Web リクエストやテストコードから個別に呼び出されることを想定している。

呼び出し元としては、`PetController` の初期化フォーム表示・作成フォーム処理・詳細更新処理、および各種テストクラスから呼び出され、飼い主と動物の関係を構築する入口となるメソッドである。

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

```mermaid
flowchart TD
    START(["addPet(pet)"])
    COND{"pet.isNew\(\)?"}
    ADD["getPets\(\).add\(pet\)"]
    RETURN(["Return / Next"])

    START --> COND
    COND -- true (新規Pet) --> ADD
    ADD --> RETURN
    COND -- false (既存Pet) --> RETURN
```

**条件ブランチの解説:**

| ブランチ | 条件 | 業務的意味 |
|----------|------|-----------|
| true 分岐 | `pet.isNew()` が `true` | Pet の `id` が `null`、すなわちまだデータベースに永続化されていない新規動物を Owner に追加する |
| false 分岐 | `pet.isNew()` が `false` | Pet の `id` が既に存在し、データベースに登録済みの動物であるため、何もしない（二重登録の防止） |

`pet.isNew()` は親クラスの `BaseEntity` で定義されており、内部で `this.id == null` を評価している。Owner エンティティ内の `pets` コレクションは `@OneToMany` でマッピングされており、JPA によって `pets` テーブルの `owner_id` フォークラムを通じて外部キー関係が維持される。

## 3. パラメータ分析

| No | パラメータ名 | 型 | 業務的説明 |
|----|---------------|------|---------------------|
| 1 | `pet` | `Pet` | 飼い主のもとに追加する動物のエンティティ。`NamedEntity` を介して `BaseEntity` を継承し、`id`（主キー）および `name`（動物の名前）を持つ。`birthDate`（生年月日）や `PetType`（動物の種類）などの属性も併せ持つ。新規登録（`id == null`）の場合は Owner のコレクションに追加され、既存登録（`id != null`）の場合は何もしない。 |
| 2 | `this.pets` | `List<Pet>` | （インスタンスフィールド）Owner が所有する動物のリスト。`@OneToMany` で `pets` テーブルと関連付けられ、`@JoinColumn(name = "owner_id")` により外部キーが設定される。`@OrderBy("name")` により名前の昇順でソートされる。追加・削除の操作対象となる集合。 |

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

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

| CRUD | SC / CBS | SCコード | エンティティ / DB | 操作の説明 |
|------|----------|---------|-------------|----------------------|
| R | `BaseEntity.isNew` | - | `BaseEntity` | `Pet` インスタンスの `isNew()` を呼び出し、`id == null` を判定して新規かどうかを確認 |
| R | `Owner.getPets` | Owner | `pets` テーブル | Owner が保持する `pets` コレクションの参照を取得し、その参照を `add()` の呼び出し元とする |

**詳細な呼び出し解析:**

| CRUD | SC / CBS | SCコード | エンティティ / DB | 操作の説明 |
|------|----------|---------|-------------|----------------------|
| R | `BaseEntity.isNew` | - | BaseEntity | `Pet` がまだデータベースに保存されていない新規エンティティかどうかを判定する。`id` フィールドが `null` であれば `true` を返す。 |
| R | `Owner.getPets` | Owner | - | Owner が所有する動物リスト（`List<Pet>`）の参照を返す。JPA により `pets` テーブルからの読み込みがマッピングされている。 |
| EXEC | `List.add` | - | - | 取得した `pets` コレクションに対して `add(pet)` を呼び出し、引数の `Pet` をコレクションに挿入する。この時点で JPA は `pets` テーブルの `owner_id` に外部キーを設定する。 |

**CRUD 分類の補足:**
本メソッド自体には SQL を直接実行する DAO メソッドや SC コード（Service Component）の呼び出しは含まれない。`@OneToMany` の `CascadeType.ALL` が設定されているため、`pets` 集合への追加は JPA によって自動的に関連する `pets` テーブルへの INSERT がトリガーされる。すなわち、`addPet()` の実行は間接的に **C (Create)** 操作を実現する。

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

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

| # | 呼び出し元（画面/バッチ） | 呼び出しチェーン（メソッドまでの全経路） | 終端（SC / CRUD / エンティティ） |
|---|----------------------|----------------------------------|-------------------------------|
| 1 | Controller:PetController | `PetController.initCreationForm` -> `Owner.addPet` | `getPets` [R], `isNew` [-] |
| 2 | Controller:PetController | `PetController.processCreationForm` -> `Owner.addPet` | `getPets` [R], `isNew` [-] |
| 3 | Controller:PetController | `PetController.updatePetDetails` -> `Owner.addPet` | `getPets` [R], `isNew` [-] |
| 4 | OwnerControllerTests.george() | `OwnerControllerTests.george` -> `Owner.addPet` | `getPets` [R], `isNew` [-] |
| 5 | PetControllerTests.setup() | `PetControllerTests.setup` -> `Owner.addPet` | `getPets` [R], `isNew` [-] |
| 6 | VisitControllerTests.init() | `VisitControllerTests.init` -> `Owner.addPet` | `getPets` [R], `isNew` [-] |
| 7 | ClinicServiceTests.shouldInsertPetIntoDatabaseAndGenerateId() | `ClinicServiceTests.shouldInsertPetIntoDatabaseAndGenerateId` -> `Owner.addPet` | `getPets` [R], `isNew` [-] |

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

**ブロック 1** — `[IF]` `(pet.isNew())` (L98)

> Pet が新規登録対象（ID が未設定）の場合、Owner の pets コレクションに追加する。

| # | 種別 | コード |
|---|------|------|
| 1 | CALL | `pet.isNew()` | `BaseEntity.isNew()` を呼び出し、`this.id == null` を評価して新規判定 |
| 2 | CALL | `getPets()` | Owner が保持する `pets` リストの参照を取得（`this.pets` を返す） |
| 3 | EXEC | `getPets().add(pet)` | 取得したリストの参照に対して `Pet` インスタンスを追加。JPA の `CascadeType.ALL` により `pets` テーブルへの INSERT がトリガーされる |

**ブロック 1.1** — `[ELSE]` implicitly `(else — pet is not new)` (L98)

> Pet が既存登録対象（ID が既に設定済み）の場合、何もしない。二重登録の防止。

| # | 種別 | コード |
|---|------|------|
| 1 | RETURN | `return;` | 何もしないままメソッドを終了する |

## 7. 用語集

| 用語 | 種別 | 業務的意味 |
|------|------|------------------|
| `Owner` | Entity | 飼い主エンティティ。`persons` テーブルと `owners` テーブルに対応し、住所・都市・電話番号などの個人情報を保持する。 |
| `Pet` | Entity | 動物エンティティ。`pets` テーブルに対応し、動物の名前・生年月日・種類（`PetType`）を保持する。 |
| `PetType` | Entity | 動物の種類（犬・猫・鳥など）を定義するエンティティ。`pets` テーブルの `type_id` 外部キーを通じて参照される。 |
| `pets` | Field | Owner が所有する動物のリスト。`@OneToMany` 関連付けにより `pets` テーブルと関連付けられる。 |
| `owner_id` | DB Column | `pets` テーブルの外部キー。どの Owner に属する動物かを特定する。 |
| `isNew()` | Method | `BaseEntity` で定義された判定メソッド。エンティティの `id` が `null` かどうかをチェックし、まだデータベースに保存されていない新規エンティティである場合は `true` を返す。 |
| `BaseEntity` | Entity | すべてのエンティティの共通親抽象クラス。`id` フィールド（主キー）および `isNew()` メソッドを定義する。 |
| `NamedEntity` | Entity | `BaseEntity` を拡張したクラス。`name` プロパティ（動物の名前など）を追加する。`Pet` および `PetType` がこれを継承する。 |
| `CascadeType.ALL` | JPA Annotation | 親エンティティの操作（ persist・merge・remove など）が子エンティティにも連鎖的に適用されることを指定する JPA アノテーション。 |
| `@OneToMany` | JPA Annotation | 1 対多のリレーションシップをマッピングする JPA アノテーション。Owner が複数の Pet を所有する関係を表現する。 |
| `@JoinColumn(name = "owner_id")` | JPA Annotation | 外部キーカラム名を `owner_id` としてマッピングすることを指定する JPA アノテーション。 |
