下書き保存テーブル
1. 目的
入力画面などで入力途中のデータを一時的に保存したい
- 多数の項目がある入力フォームは、内容が未完成でも現在の入力内容を一時的に保存したいというニーズがあり、UX的にも対応したいところである
- WEBアプリはブラウザ上で入力する為、不意の操作ミス(ブラウザバック、リロード、ブラウザを閉じるetc...)でデータをロストする可能性が否めない
- したがって、多数の項目を持つ入力フォームに、入力途中のデータを保存し、再度読み出す機能を実装したい
2. 課題
不完全なデータをDBに保存するとデータ不整合が発生する
- 外部キー制約やNot Null制約を設定しているテーブルに不完全なデータを投入すると制約に違反する為、データを登録できない
- かと言って、制約を緩めると不正なデータを受け入れることになるので、データ不整合を誘発してしまう
3. 解決策
入力データをシリアライズして下書きデータ保存テーブルに保存する
- 下書きデータを直接本丸のテーブルに保存するのではなく、下書き専用のテーブルを用意し、そこに下書きを保存するようにする
- 大雑把な実現方法は以下の通り:
- (1) 下書きデータ保存テーブルを作成する
- (2) 入力フォームのデータをJSONなどでシリアライズする
- (3) 下書きデータ保存テーブルに保存する
- (4) 必要に応じて読み出す
下書き保存テーブル
-- xxx下書きテーブル
CREATE TABLE xxx_draft (
id int AUTO_INCREMENT PRIMARY KEY, -- 主キー
uuid varchar , -- UUID
kind varchar, -- データ種別
version int, -- データバージョン
value text, -- シリアライズ済みJSON
);
id:
uuid:
- UUID
- データを取り出す為のUUID
- 例えば、URLに含めるなどの利用法を想定しているが、不要なら省略してもよい
kind:
- データの種別を表す値
- 例えば
article_draftなど
- アプリケーションはこの値を参照してデータを識別・適切なオブジェクトにマッピングする
version:
- データのバージョン
- フォームの内容が変わった場合、古いバージョンの下書きデータは読み出しても項目の不整合などでエラーが発生する可能性がある
- そのような事故を防ぐ為に、バージョン番号を持ち、読み出し側でバージョンに対応した処理を行えるようにしておく
- セマンティックバージョンを適用するよりは、単純な整数値の連番の方がよい(バージョン番号の付与で迷うことがないので)
value:
- シリアライズされたJSON文字列
- JSON型を使ってもよいが、下書きテーブルの検索をするユースケースは考えにくいので基本的には文字列型でよいと思われる
4. メリット
データの整合性を保ちつつ、下書きデータの保存ができる
- 完全なデータが保存されるテーブルには制約を設定してデータ整合性を守りつつ、不完全なデータの受け入れ専用テーブルを設けることで入力内容の下書き保存を達成できる
5. デメリット
6. 注意
下書きはあくまでも下書きとして扱う
- 下書きテーブルはそれ単体で独立していなければならない
- 下書きはあくまでも一時的なデータかつ不完全なデータなので、下書きテーブルのデータに依存するようなテーブルを作ってはならない
- 同様に下書きテーブルとその他のテーブルをJOINするようなSQLも原則として書くべきではない
参考資料