下書き保存テーブル
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
{CONTEXT} {DATA_TYPE}, -- データのコンテキスト
data text, -- シリアライズ済みJSON
version int, -- データバージョン
);
-
id
:
-
uuid
:
- UUID
- データを取り出す為のUUID
- 例えば、URLに含めるなどの利用法を想定しているが、不要なら省略してもよい
-
{CONTEXT}
:
- データのコンテキストを判別する値
- データを保存したユーザーと紐付けが可能なデータがセットされる
- 例えば、入力しているユーザーのユーザーIDやセッションIDなど
-
data
:
- シリアライズされたJSON文字列
- JSON型を使いたくなるところだが、このJSONの内容を検索するユースケースはまず存在せず、インデックスの作成コストが無駄になるだけなのでおすすめしない
-
version
:
- データのバージョン
- フォームの内容が変わった場合、古いバージョンの下書きデータは読み出しても項目の不整合などでエラーが発生する可能性がある
- そのような事態を防ぐ為に、バージョン番号を持ち、読み出し側でバージョンに対応した処理を行えるようにしておく
- 下手にセマンティックバージョンを適用するのではなく、単純な整数値の連番の方がよい(バージョン番号の付与で迷うことがないので)
4. メリット
データの整合性を保ちつつ、下書きデータの保存ができる
- 完全なデータが保存されるテーブルには制約を設定してデータ整合性を守りつつ、不完全なデータの受け入れ専用テーブルを設けることで入力内容の下書き保存を達成できる
5. デメリット
6. 注意
下書きはあくまでも下書きとして扱う
- 下書きテーブルはそれ単体で独立していなければならない
- 下書きはあくまでも一時的なデータかつ不完全なデータなので、下書きテーブルのデータに依存するようなテーブルを作ってはならない
- 同様に下書きテーブルとその他のテーブルをJOINするようなSQLも原則として書くべきではない
参考資料