S2JDBC-Genの紹介 その6 − マイグレーション

S2JDBC-GenマイグレーションRailsマイグレーションとは違います。Railsマイグレーションはバージョン間のスキーマの変更分のみを適用しますが、S2JDBC-GenDROP&CREATEで一旦全部消してから作り直すというスタンスです(データはダンプしてロード)。

運用がはじまったら「一旦全部消してから作り直す」というのはできませんが、開発中はこっちのほうがわかりやすいんじゃないかと思います。S2JDBC-Genは開発に主眼を置いています。

Railsのmigrationで、開発時は変更履歴が不要という意見があるようですね。
migration の問題

マイグレーション

マイグレーションはmigrateというAntタスクで行います。前回、SCHEMA_INFOというテーブルとddl-info.txtというファイルでそれぞれバージョンを管理しているといいました。簡単に説明します。

SCHEMA_INFOテーブル

これはデータベースのスキーマのバージョンを管理するテーブルです。ここで管理されるバージョン番号はマイグレーション元のバージョン番号になります。migrateをすると新しいバージョン番号で更新されます。

ddl-info.txtファイル

これはエンティティやエンティティから生成されたDDLのバージョンを管理するファイルです。ここで管理されるバージョン番号はマイグレーション先のバージョン番号になります。gen-ddlすると番号が更新されます。

S2JDBC-Genマイグレーションは、SCHEMA_INFOテーブルのバージョン番号でスキーマDROPしてddl-info.txtのバージョン番号でスキーマをCREATEします。バージョン番号は、DDLを管理するディレクトリの名前に対応します。DDLを管理するディレクトリがどんなものかというとこんなものです。

バージョン番号 1 から 2 へのマイグレーションが行われる場合は、db/migrate/0001/dropの下のDDLスキーマを削除した後、db/migrate/0002/createの下のDDLスキーマを再作成します(CSVがあればデータのロードも行います)。

シナリオ例

シナリオで考えてみるとイメージしやすいと思います。前提として、次の条件が成り立っているものとします。

シナリオは次のようなものです。今、Subversionのtrunkのddl-info.txtで管理されているバージョン番号も、各開発者のDBに含まれるSCHEMA_INFOテーブルのバージョン番号も 1 だとします。

  1. Aさんがエンティティにプロパティを追加して、gen-ddlします。このとき、ddl-info.txtのバージョン番号が 1 から 2 に更新されます。
  2. Aさんは自分の環境でmigrateして自分のデータベーススキーマにエンティティの変更を反映させます(テーブルにカラムを追加します)。このとき、SCHEMA_INFOのバージョン番号は 1 から 2 に更新されます。
  3. Aさんは、migrateが成功し、その後のテストも成功することを確認したら、Subversionにエンティティのjavaファイル、生成したDDLddl-info.txtをコミットします。Aさんの作業はひとまずこれで終わりです。
  4. BさんはSubversionから最新データを取得します。このときBさんのSCHEMA_INFOのバージョン番号はまだ 1 ですが、ddl-info.txtはAさんが更新したものを取得しているのでバージョン番号はすでに 2 になっています。
  5. BさんはDDLが変更されていることに気づいたらmigrateを実行します。すると、SCHEMA_INFOのバージョン番号 1 でDROPddl-info.txtのバージョン番号 2 でCREATEが行われ、Bさんの開発用DBも最新のスキーマになります。このとき、SCHEMA_INFOのバージョン番号も 1 から 2 に更新されます。

このシナリオは、最新のバージョンへのマイグレーションを行うものですが、もちろん特定のバージョンを指定したマイグレーションを行うこともできます。

ファイル内の任意のSQLを実行するタスク

これで、S2JDBC-Genのだいたいの機能は紹介できました。細かいところはいろいろありますけど。

次回はファイルに記述された任意のSQLを実行するタスクを紹介します。SQLステートメントだけでなく、Transact-SQLPL/SQLのようなSQLのブロックも実行できるので便利じゃないかと思います。migrateタスクの内部で使っている機能ですが、単独のタスクとしても使えるのでちょっとしたユーティリティとして使ってもらえればと思います。