これは、リレーショナルテーブルのインピーダンス不整合に対する古典的なオブジェクト指向設計です。あなたが説明したテーブルデザインは、「サブクラスごとのテーブル」として知られています。最も一般的な3つのデザインは、オブジェクトがアプリで実際にどのように見えるかと比較して、すべて妥協点です。
- 具体的なクラスごとのテーブル
- 階層ごとのテーブル
- サブクラスごとのテーブル
「テーブルに100列があり、ほとんどの値がNULLである」という、気に入らないデザインは2です。1つのテーブルで、特殊化階層全体を格納します。これは、次のようなあらゆる理由で柔軟性が最も低くなります。アプリで新しいサブクラスが必要な場合は、列を追加する必要があります。記述した設計は、product_typeの値で記述された新しいサブクラステーブルを追加することで拡張できるため、変更に対応しやすくなります。
残りのオプション(1.具象クラスごとのテーブル)は、各特殊化テーブルのすべての共通フィールドの実装に重複があるため、通常は望ましくありません。ただし、利点は、結合を実行する必要がなく、サブクラステーブルを非常に大規模なシステムの異なるdbインスタンスに配置できることです。
あなたが説明したデザインは完全に実行可能です。以下のバリエーションは、ORMツールを使用してCRUD操作を実行した場合の外観です。各サブクラステーブルのIDが、階層内の親テーブルに対するFK値であることに注意してください。優れたORMは、product.idとproduct.product_type_idの識別子の値のみに基づいて、正しいサブクラステーブルCRUDを自動的に管理します。 ORMの使用を計画しているかどうかに関係なく、hibernateの結合されたサブクラスのドキュメントを見て、設計上の決定を確認するだけです。
product
=======
id INT
product_name VARCHAR
product_type_id INT -> Foreign key to product_type.product_type_id
valid_since DATETIME
valid_to DATETIME
magazine
========
id INT -> Foreign key to product.product_id
title VARCHAR
..
web_site
========
id INT -> Foreign key to product.product_id INT
name VARCHAR
..