11
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

DependentMapping & EmbeddedValue & SerializedLOB

Posted at

10.DependentMapping & EmbeddedValue & SerializedLOB.png

Dependent Mapping と Embedded Value と Serialized LOB は、いずれもオブジェクトの属性が作る構造をどのようにテーブルの構造に対応付けるかに関するパターンです。

中でも Dependent Mapping は少し理解しにくいパターンですが、知ってしまえば有用なパターンです。

リレーショナルデータベースでは、id カラムのようなサロゲートキーが必要そうに見えても、必ずしもそうした全体固有キーが必要でない場合があります。カラム複数で主キーを成す、複合主キーがナチュラルキーになる場合があるからです。

ゲームに登場する武器の属性に、炎や雷といった複数の属性を付与できる仕様があるとしましょう。この関係は、もし炎や雷の属性の詳細として別のテーブルを参照する設計にした場合は、Association Table Mapping で多対多に関連付けたようなかたちになります。weapon_attribute テーブルの weapon_id と attribute_id の組み合わせは、すべての行についてユニークになります。このセットは、もし別のカラムが増えた場合でも、複合主キーとして有効です。

では、炎や雷といった属性に別テーブルに置くほどの詳細が必要なく、文字列か整数のカラムで済む場合はどうでしょうか。伝説の剣 (id=1) には炎の属性が 50%、雷の属性が 50%、職人の斧 (id=2) には水の属性が 100%、とデータ化していくと、このような表になります。

weapon_id element retio
1 fire 50
1 thunder 50
2 water 100

weapon_id と element の組はユニークで、ナチュラルな複合主キーにできます。「この武器へのこの属性割当だけ」という、妙な問い合わせが必要でないなら、この表にサロゲートキーは必要ありません。こんなもの、特定の武器に従属させないと意味がありませんよね。

オブジェクトへのマッピングにおいても、武器を id で特定できればよく、属性はつねに武器から辿らえるのが自然です。クラスは2種類あるけれど、物としてはそれで一体の構造になってきます。このとき、武器には Identity Field が必要ですが、属性には Identity Field が必要ありません。変更をデータベースと同期するときは、属性を個別に管理せず、属性を巻き込んだ武器全体をひとつの管理単位とします。この形になったとき、武器はエンティティとなり、属性のコレクションは Dependent Mapping で武器エンティティの一部となります。

Embedded Value は Value Object (後で出てきます) を属性に持つオブジェクトの扱いにおいて、同様にエンティティ数の節約をする方法です。

リレーショナルデータベースのデータ型には、数値、文字列、日時といった、決まったものしか準備されていません。いっぽう、Value Object はいくらでも種類を増やせるうえ、内部に持つ値も、ひとつの整数や文字列にエンコードできない場合はよくあります。このとき Foreign Key Mapping を使わずに、Value Object の内部構造をテーブルのカラムに横展開してマッピングしようとするのが Embedded Value です。

そもそも Value Object とみなしたのだから、一意性には意味がありません。エンティティと考えるのは不向きです。エンティティはクエリの対象ですが、何かの色コードの RGB 値だけを個別取得したいなんてニーズは、まずありませんね。

Serialized LOB は、より複雑な Value Object をカラムに押し込むアイデアです。

HTML DOM のような、何層あるかわからない再帰的構造を持つ Value Object は、横展開することができません。もし各要素をエンティティとするなら、別テーブルに出して頑張ってツリー構造を表現するべきですが、そうでないなら、明らかに過剰設計です。リレーショナルモデルは再帰的ツリー構造には向いていません。

そこで、JSON や XML、あるいはプログラム言語のオブジェクトシリアライズを使い、巨大なオブジェクトを文字列やバイト列にエンコードたものを、文字数の上限がないテキストカラム、あるいは LOB/BLOB と言われるデータ列用の単一カラムに詰め込むのが、Serialized LOB パターンです。

Serialized LOB を使えば何でもマッピングできると思うかもしれませんが、これはデータベース技術の都合上、アンチパターンとされています。安易にこうしたエンコードによる押し込みをすると、データにインデックスを付けることも、リレーショナルデータベースが得意なテーブルの連結もできなくなるからです。また、必ずデータを復元できる保証もありません。デシリアライズしたとき、マッピング対象のクラス詳細が、保存時とは異なっていることもあります。復元時の完全性などなくてもいいから、ただ保存できさえすればいいのだ、と言い切れる場合にのみ、有効なパターンです。

11
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?