きり丸の技術日記

技術検証したり、資格等をここに残していきます。

Flywayで特定のDBだけSQLを実行する(Spring, vender, Postgres)

小ネタ。なお、私のユースケースを満たせていなかったので、調査結果だけです。

環境

  • Java
    • 17
  • org.flywaydb
    • 8.5.13
  • org.springframework.boot
    • 2.7.7

対応

設定ファイルの変更

PostgresやOracle等々で実行するSQLを変更するために、spring.flyway.locationsclasspath:db/migration/{vendor}を設定します。

spring.flyway.locations: classpath:db/migration/{vendor}

ディレクトリを作成する

ディレクトリを用意します。{vender}で置換できるのは、こちらのJavaファイルを確認してください。

今回は、h2, postgresql, mysqlを用意します。

- db
  - migration
    - h2
      - マイグレーションSQL
    - postgresql
      - マイグレーションSQL
    - mysql
      - マイグレーションSQL

後は、起動時、テスト時にDatabaseDriver名を元に特定のディレクトリのSQLが実行されていることが分かります。どのような動作確認をしていたかは、ソースコードで確認してください。

ソースコード

解決したかったユースケース

テスト時はH2を使用し、アプリケーション起動時はPostgresを使用しています。

ローカル環境構築時には、動作確認できるようにFlywayでマスタデータだけでなく、トランザクションデータを登録しようとしていました。

ただ、設定ファイルを書き換えたりする手間を考えると、逆にわかりづらいです。理想としては、{vender}の上位ディレクトリは汎用的なSQLを流しつつ、{vender}ディレクトリにトランザクションデータを登録させようとしていました。

- db
  - migration
    - 汎用SQL
    - postgresql
      - トランザクションSQL

このように配備したところ、子孫ディレクトリのSQLまで実行するため、汎用SQLもトランザクションSQLも実行されてしまいました。さらにclasspath:db/migration/{vendor}と設定すると、上位ディレクトリの汎用SQLが実行されなくなりました。

使えるユースケースもあると思いますが、かなり限定的だと思うので、私は使いません。以前、私が書いた記事の設定で十分です。

終わりに

この機能自体はFlywayの公式には載っていません。Spring側のDatabaseDriverで判別すると記載されているとおり、Springのラッパーライブラリ側で解決しています。

Flywayの公式ドキュメントを読んで存在せず、Spring側の公式ドキュメントを読んでようやく存在を認識しました。教えていただいたMitz Shiibaさん感謝です。

参考情報

類似情報

Gitのコミット時間を変更する(git commit --amend --date="`date -R`")(git squash と組み合わせる)

小ネタ。

環境

  • Git
    • git version 2.24.1.windows.2

対応

次のコマンドを実行すると、最新のコミット更新時間が現在時刻になります。また、特定の時間に更新したい場合は、Git internal format、RFC2822、ISO 8601形式のどれかで渡してください。

# 現在時刻で更新
git commit --amend --date="`date -R`"

# 特定の日時で更新
git commit --amend --date="Wed Feb 18 22:34:51 2022 +0900"

終わりに

私は、作業中は別ブランチにして、ちょっとでも変更したら別ブランチにコミットを積んでいます。最終的には全部のコミットをsquashして、元のブランチにcherry-pickすることで、Gitネットワークをきれいに保つことを意識しています。

ただ、この方法には問題があり、コミットの更新時間が一番初めのコミットにまとめられてしまいます。

Gitネットワークはきれいでも、Gitの更新履歴が順序よく並ばなくなってしまうので、問題視していました。今回の記事により、squashしたコミットの更新時間を最新化できるので、更新履歴に違和感を感じることがなくなりました。

なお、普段よく使用しているIntelliJ IDEAでは、コミット時間の変更はできそうになかったです。GUIで変更できればよかったのですが…。とりあえず、方法が分かってよかったです。

参考情報

Javaで1行でNull許容の配列を作りたかった

結局、願ったとおりに動かなかったので、思考錯誤したときのメモだけ残します。

環境

  • Java
    • 17

対応

Collections.singletonList(T o)を使用することで、1行でnull許容した配列を作成できます。

動作確認

1行で配列を作成する方法は、List.of(), Arrays.asListのどちらもありますが、NotNull制約があるので、作成できません。

ArrayListはnullも追加可能ですが、初期配列の作成時には使えません。そもそも、初期配列の作成時のパラメータ自体が配列となるため、内部処理にてエラーが発生します。

var sample = new ArrayList<>();
assertAll(
    () -> assertThatThrownBy(() -> List.of(null))
        .isInstanceOf(NullPointerException.class),
    () -> assertThatThrownBy(() -> Arrays.asList(null))
        .isInstanceOf(NullPointerException.class),
    () -> assertThatThrownBy(() -> new ArrayList<>(null))
        .isInstanceOf(NullPointerException.class),
    () -> Collections.singletonList(null),
    () -> sample.add(null)
);

本当にやりたかったこと

戻り値としては配列で返却したいものの、内部の処理としては単数で受け取るメソッドがあるとします。現状、それを処理するためには4行の処理が必要だったので、1行に短縮したかったのです。

@Service
@RequiredArgsConstructor
public class SalesService {
  private final SalesComponent component;

  // NOTE: このコードは動かないので、イメージです
  public List<String> execute() {
    // あまり意味がないけど、4行必要
    var list = new ArrayList<String>();
    var result = component.execute();
    list.add(result);
    return list;

    // 1行でシンプル!
    return Collections.singleton(component.execute());
  }
}

なお、配列にNullを許容するメリットはあるかというと、ありませんでした。

Springの設定で、nullの場合は値を出力しない設定があります。

spring.jackson.default-property-inclusion: NON_EMPTY

こちらの設定をすることで、配列にnullを許容しつつ、JSONのResponseBodyには影響しないと考えていました。しかし、上記の設定では期待とおりの設定はできません。インスタンスのフィールドが一部nullだった時の挙動だけが変わりました。インスタンスそのものがNullとして設定されていた場合は、出力されてしまいます。しかも、空文字列や空配列になるのではなく、nullと出力されてしまいました。

{
  "salesList": [null]
}

結局、素直にnullが入らないように処理しています。

@Service
@RequiredArgsConstructor
public class SalesService {
  private final SalesComponent component;

  public List<String> execute() {
    var result = component.execute();
    if (result == null) {
      return List.of();
    } else {
      return List.of(result);
    }
  }
}

ソースコード

細かい挙動確認等々は、次のソースコードを確認してください。

終わりに

1行で書きたかったです…。もしくは、初期設定時やaddするときのパラメータは許容するものの、配列としてはパラメータを無視するようなメソッドがあるとうれしいのですが。まぁ、限定的な要望ですので、素直に処理するのが簡単ですね。

類似情報