読者です 読者をやめる 読者になる 読者になる

sql-maven-pluginでDBの楽々初期化

はじめに

maven2で、DBの初期化をしたいときに便利なsql-maven-pluginというmavenプラグインがあります。
ちょっと見ない間にバージョンが1.3まで進んでいました。

バージョン1.0までは・・・・

実はこのプラグイン、バージョン1.0までは、

  • (A) SQLファイルのencoding指定ができない
  • (B) 複数のSQLファイルの実行順序が指定できない

などのかなり致命的な問題がありました。

バージョン1.0/1.1-SNAPSHOTまでのバッドノウハウその1

(A)については、以前にこの日記で言及したこともあります。

あの時点では、1.1-SNAPSHOTバージョンを利用してごまかしていましたが、1.1正式版以降では問題なくencodingパラメータが使えるようになっていて、解決済みですね。

バージョン1.0/1.1-SNAPSHOTまでのバッドノウハウその2

また(B)については、以前はexecution設定は書いた順序通りに実行されるということから、ファイル毎にexecution要素を分けて書くという代替手段を使っていましたが、これが冗長で見づらくてかなりイヤンな感じでした。


これもバージョン1.1以降では、orderFileというパラメータが導入されており、これに"ascending"指定するとファイル名の昇順でソートした順序で実行されるようになりました。ファイル名先頭を0パディングの通番にしておけば問題なく実行順序を制御できます。素晴らしい。

まとめ

というわけで、バージョン1.1-SNAPSHOTまでの以下のような冗長すぎる記述が・・・・

  <build>
    <finalName>Database initializing</finalName>
    <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>sql-maven-plugin</artifactId>
        <version>1.1-SNAPSHOT</version>
        <dependencies>
          <dependency>
            <groupId>org.apache.derby</groupId>
            <artifactId>derby</artifactId>
          </dependency>
        </dependencies>
        <configuration>
          <driver>org.apache.derby.jdbc.EmbeddedDriver</driver>
          <url>jdbc:derby:db/sample;create=true</url>
          <encoding>utf-8</encoding>
          <autocommit>true</autocommit>
        </configuration>
        <executions>
          <execution>
            <id>recreate-db</id>
            <phase>process-resources</phase>
            <goals>
              <goal>execute</goal>
            </goals>
            <configuration>
              <fileset>
                <basedir>${basedir}</basedir>
                <includes>
                  <include>db/01-dropdb_derby.sql</include>
                </includes>
              </fileset>
              <onError>continue</onError>
              <skip>false</skip>
            </configuration>
          </execution>
        </executions>
        <executions>
          <execution>
            <id>recreate-db</id>
            <phase>process-resources</phase>
            <goals>
              <goal>execute</goal>
            </goals>
            <configuration>
              <fileset>
                <basedir>${basedir}</basedir>
                <includes>
                  <include>db/02-createdb_derby.sql</include>
                </includes>
              </fileset>
              <onError>continue</onError>
              <skip>false</skip>
            </configuration>
          </execution>
        </executions>
        <executions>
          <execution>
            <id>recreate-db</id>
            <phase>process-resources</phase>
            <goals>
              <goal>execute</goal>
            </goals>
            <configuration>
              <fileset>
                <basedir>${basedir}</basedir>
                <includes>
                  <include>db/03-datas_derby.sql</include>
                </includes>
              </fileset>
              <onError>continue</onError>
              <skip>false</skip>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
〜(省略)〜
     <pluginRepositories>
       <pluginRepository>
         <id>Codehaus Snapshots</id>
         <url>http://snapshots.repository.codehaus.org/</url>
       </pluginRepository>
     </pluginRepositories>


1.1以降では、以下のようにすっきりと書くことができるようになりました。

  <build>
    <finalName>Database initializing</finalName>
    <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>sql-maven-plugin</artifactId>
        <version>1.3</version>
        <dependencies>
          <dependency>
            <groupId>org.apache.derby</groupId>
            <artifactId>derby</artifactId>
          </dependency>
        </dependencies>
        <configuration>
          <driver>org.apache.derby.jdbc.EmbeddedDriver</driver>
          <url>jdbc:derby:db/sample;create=true</url>
          <encoding>utf-8</encoding>
          <autocommit>true</autocommit>
        </configuration>
        <executions>
          <execution>
            <id>recreate-db</id>
            <phase>process-resources</phase>
            <goals>
              <goal>execute</goal>
            </goals>
            <configuration>
              <fileset>
                <basedir>${basedir}</basedir>
                <includes>
                  <include>db/01-dropdb_derby.sql</include>
                  <include>db/02-createdb_derby.sql</include>
                  <include>db/03-datas_derby.sql</include>
                </includes>
              </fileset>
              <onError>continue</onError>
              <skip>false</skip>
              <orderFile>ascending</orderFile>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>


うーん。すっきり。


目下の悩み

  • 最近だともっと使いやすいmavenプラグインが出てきてますかねぇ?
  • 明示的に指定したときだけDBの初期化処理を実行する良い方法は?
    • 上記の記述だと、process-resourcesフェーズを通るときに毎回初期化されてしまうため、困る。
    • 今はpom-setup.xmlという別ファイルで初期化処理を記述してしのいでいるけど、HudsonでCIするときに困ってます。
    • 複数のpom.xmlファイルを扱えるようになっていればこの方法でも良かったのだけど・・・。

15:30追記

上記の 「明示的に指定したときだけDBの初期化処理を実行する良い方法は?」だけど、解決したっぽい。


executions/executionに対する理解がちょっと間違っていたようです。


今のところの補正版理解では

  • executionは、あるphaseに伴って自動的にプラグインのゴールが実行されるように指定する目的で使われる。
    • execution配下のconfigurationは、phaseに伴って自動実行された場合にのみ追加で利用される。コマンドラインで直接プラグインのゴールを指定したときには無視される。
  • plugin要素直下のconfiguration要素は、phase指定の場合でも、直接ゴール指定の場合でもどちらでも使われる。

という感じ。これでも間違ってたら指摘してください。


つまり、他のSQL設定を実行するような使い分けが不要で、かつ、明示的にゴール指定したときだけSQL実行をして欲しいのであれば、

  <build>
    <finalName>Database initializing</finalName>
    <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>sql-maven-plugin</artifactId>
        <version>1.3</version>
        <dependencies>
          <dependency>
            <groupId>org.apache.derby</groupId>
            <artifactId>derby</artifactId>
          </dependency>
        </dependencies>
        <configuration>
          <driver>org.apache.derby.jdbc.EmbeddedDriver</driver>
          <url>jdbc:derby:db/sample;create=true</url>
          <encoding>utf-8</encoding>
          <autocommit>true</autocommit>
          <fileset>
            <basedir>${basedir}</basedir>
            <includes>
              <include>db/01-dropdb_derby.sql</include>
              <include>db/02-createdb_derby.sql</include>
              <include>db/03-datas_derby.sql</include>
            </includes>
          </fileset>
          <onError>continue</onError>
          <skip>false</skip>
          <orderFile>ascending</orderFile>
        </configuration>
      </plugin>
    </plugins>
  </build>

と設定しておいて、

$ mvn sql:execute

と実行すればOKということ。


おお、ついに長年の課題が解決できた!?