PoEAA ch12 Class Table Inheritance

PoEAA勉強メモ

出典: 


Class Table Inheritance

Represents an inheritance hierarchy of classes with one table for each class.

  • 1クラス1テーブル

    • 抽象クラス含む

How It Works

  • 1具象クラスに複数のテーブルが対応する
  • 複数のテーブルの、対応する行の紐付けはどうするの

    • 親クラスと子孫クラスとで共通のPKを使う

      • footballersテーブルのid=101のレコード
      • playersテーブルのid=101のレコード
    • 親クラスのテーブルへのFKを持つ

      • footballersテーブルのid=101のレコードはplayer_id=234をもつ
      • playersテーブルのid=234のレコードが対応する
  • 実装上最大の問題 — 効率よくデータフェッチするにはどうするの

    • テーブルごとにクエリするのは明らかに非効率
    • JOINで回避可能

      • だが、RDBMSの最適化的にJOINは3-4回が限度、それより多いと遅くなる
  • 抽象化したオブジェクトのコレクションを取得するとき、どのテーブルをJOINすればよいかわからない問題

    • aFootballerを取得するならfootballersテーブルとplayersテーブルとをJOINすればよい
    • playersを取得する場合、どうすればいいの?

      • footballers?
      • cricketers?
      • bowlers?
    • OUTER JOINが必要

      • 【補】footballerのidで上記テーブルを全部INNER JOINすると、result setは0件になってしまう

        • 当該idのcricketerレコードやbowlerレコードが存在しないため
      • 非標準
      • 遅い
  • 解決策: idと型フィールドをもつrootテーブルを作る

    • 型フィールドを使ってよしなに最小限JOINできる
    • ただし、複数クエリ必要

      • 【補】具体的にどんな?

        1. rootテーブルへの{id, 型フィールド}クエリ
        2. Domain Modelクラスのテーブルへのクエリ

          • JOINしたりUNIONしたり

            • カラム定義が異なるとUNIONできないのでselect listがごちゃごちゃに
            • UNIONしないとクエリ数さらに増える

When to Use It

  • Single Table Inheritance, Concrete Table Inheritanceと比べたメリデメ

    • メリ

      • 無駄カラムない

        • 理解しやすい
        • 空間効率よい
      • Domain Modelクラスとの対応が直接的でわかりやすい
    • デメ

      • 複数のテーブルからデータフェッチする必要がある

        • JOINする
        • or 複数回クエリしてメモリ上で合体する
      • Domain Modelクラスのフィールドのリファクタリングがテーブル定義の変更に直結
      • 親クラスのテーブルが性能上のボトルネックになりがち

        • アクセス集中
        • 【補】ロッキングしやすい
      • (一般論)高度に正規化すると、「その場限りのクエリ」が理解しづらくなる

        • 【所感】正規化じゃなくね?結合従属な垂直分割ではあるが

          • 第6正規形に近くて遠い
  • 複数のTable Inheritanceパターンを混用してもよい

    • 例:

      • クラス階層の最上位だけClass Table Inheritance
      • 下位はConcrete Table Inheritance

Furhter Reading

  • IBMのRoot-Leaf Mapping [Brown et al.]

コード例

  • かいつまんでメモ

    • Mapperつくる

      • 下記の依存を断ち切る

        • Domain Modelクラス
        • DBゲートウェイクラス
    • サンプルコードではJOINせず複数回クエリしてる

      • Domain Modelと同じクラス階層でMapperをつくる
      • 各Mapper(抽象/具象)は1つのテーブルに対応している