勉強日記

チラ裏

PoEAA ch12 Class Table Inheritance

martinfowler.com


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つくる
    • サンプルコードではJOINせず複数回クエリしてる
      • Domain Modelと同じクラス階層でMapperをつくる
      • 各Mapper(抽象/具象)は1つのテーブルに対応している