ER図とGoogle App Engine

最近の趣味プログラミングでは、ER図からGAEj用のEntityクラスとDaoクラスを自動生成するプログラムを作っている。
 
少し前に書いた日記で、「RDBMSでのユニークFKをGAEでのキーに持ってきた方が良い」みたいなことを書いたけれども、ER図で言うと、「(1)対(0または1)」のリレーションが貼られた部分が、それにあたる。
 

                                                                                                                      • -

■パターン1
 

class A
- a (PK) NOT NULL

 

class B
- b (PK) NOT NULL
- a (FK01->A) NOT NULL

 

A : B
1 : 0または1
                                                                                                                      • -

 
上記みたいな場合である。
 
ちなみにリレーション対象のフィールドが複数あっても、複数個の型違いの変数からシリアライズ文字列は作れるので、そのシリアライズ文字列をキーにすれば良い。
 

                                                                                                                      • -

■パターン2
 

class A2
- a (PK) NOT NULL
- a2 (PK) NOT NULL

 

class B2
- b (PK) NOT NULL
- a (FK01->A2) NOT NULL
- a2 (FK01->A2) NOT NULL

 

A2 : B2
1 : 0または1
                                                                                                                      • -

 
じゃあ、次のようなパターンはどうすれば良いだろうか。
 

                                                                                                                      • -

■パターン3
 

class X
- x (PK) NOT NULL

 

class Y
- y (PK) NOT NULL

 

class Z
- z (PK) NOT NULL
- x (FK01->X) NOT NULL
- y (FK02->Y) NOT NULL

 

X : Z
1 : 0または1

 

Y : Z
1 : 0または1
                                                                                                                      • -

 
これはたぶん、できない。
以下の様に書き直すしかない。
 

                                                                                                                      • -

■パターン4
 

class X
- x (PK) NOT NULL
- z (FK01->Z) NULLABLE

 

class Y
- y (PK) NOT NULL
- z (FK02->Z) NULLABLE

 

class Z
- z (PK) NOT NULL

 

X : Z
1 : 0または1

 

Y : Z
1 : 0または1
                                                                                                                      • -

 
「なんだ、パターン1よりパターン4のほうが、自由度が高いんじゃないか! パターン1は必要ないね!」
と思ったら、大間違い。
パターン1のAに、仮想エンティティ(データベース上にエンティティの種類さえ本当は存在しないけれども、存在しているものと過程してER図上には表記する)を用いてやることで、「ユーザが自由入力の文字列ID」や「とあるIDのスレッドのn発言目」といった、出現頻度の高いユニーク制約の多くを、ER図上で表現することができる。
 
逆にパターン4は、ほとんど使わない。
(新しいエンティティを足すのに、2つもエンティティを操作しなければならないというのが、このパターンがGAEでほとんど使われない理由。別々のエンティティグループなら2回の操作は別々のトランザクションで行われることになるし、同じエンティティグループにしなければならないという制限は、それはそれで大きな制限になる場合が少なくない)
 
最後に、パターン3と良く似ている様で全然違う、以下のパターン。
 

                                                                                                                      • -

■パターン5
 

class X
- x (PK) NOT NULL

 

class Y
- y (PK) NOT NULL

 

class Z
- z (PK) NOT NULL
- x (FK01->X) NOT NULL
- y (FK01->Y) NOT NULL

 

X : Z
1 : 0以上

 

Y : Z
1 : 0以上
                                                                                                                      • -

 
これはGAE上で実装可能なのだが、ER図上は何とも書きづらい。
そういう時は、ER図上では以下の様に表現する。
 

                                                                                                                      • -

■パターン6
  

class X
- x (PK) NOT NULL

 

class Y
- y (PK) NOT NULL

 

class W (コメント:仮想エンティティ)
- x (PK) NOT NULL (コメント:FK01->X)
- y (PK) NOT NULL (コメント:FK01->Y)

 

class Z
- z (PK) NOT NULL
- x (FK01->W) NOT NULL
- y (FK01->W) NOT NULL

 

X : W
1 : Y個

 

Y : W
1 : X個

 

W : Z
1 : 0または1

 
(※ WはXとYのクロス積個、仮想的に存在しているものとみなす)

                                                                                                                      • -

 
ね、仮想エンティティ、便利でしょ。