W liquibase definiujesz migracje przez XMLa, a w Flyway piszesz natywnym SQLem.
W Liquibase też, jak najbardziej, możesz pisać natywnym SQL. Różnica polega raczej na nieco bardziej zaawansowanej obsłudze skryptów w Liquibase, możliwościach uruchomienia niektórych change setów w zależności od np. rodzaju bazy danych itd. Liquibase, czysto teoretycznie, może wydawać się lepszym narzędziem, gdy chcemy obsługiwać wiele baz danych.
Możesz np. obsługiwać sobie zmienne:
<property name="trueValue" value="1" dbms="oracle"/>
<property name="trueValue" value="true" dbms="postgres"/>
<!-- I potem robisz insert -->
<insert tableName="MY_TABLE">
<column name="MY_UNIQUE_ATTR">Fwij32sX<column>
<column name="ENABLED">${trueValue}</column>
</insert>
Tego używam jednak dość rzadko, bo jeśli tworzymy skrypty specyficzne dla danej RDBMS, to prędzej czy później, tworzenie takich jednolitych skryptów dla wszystkich baz może się okazać bardziej uciążliwe niż tworzenie osobnych skryptów.
Albo uruchamiać osobne changeSety w zależności od dbms:
<changeSet id="initialSchema" author="me" dbms="postgres,mysql">
<!-- ... -->
</changeSet>
Ja cenię sobie jeszcze opcję rollback
w Liquibase (aczkolwiek, używane z reguły tylko na stanowiskach developreskich):
<changeSet id="initialSchema" author="me" dbms="postgres,mysql">
<!-- ... -->
<sql>
INSERT INTO MY_TABLE (MY_UNIQUE_ATTR, ENABLED) VALUES ('123', TRUE);
</sql>
<!-- Jakieś inne instrukcje, które mogą zakończyć się błędem -->
<rollback>
<sql>
DELETE FROM MY_TABLE WHERE MY_UNIQUE_ATTR = '123';
</sql>
</rollback>
</changeSet>
Pewnie jeszcze kilka opcji, które by Cię interesowały, można by wymienić, ale to nadawałoby się na osobny tutorial z Liquibase. :)
Nie znam tak dobrze funkcjonalności Flyway, którego używałem dotychczas jako prostego narzędzia do wgrywania kolejnych skryptów SQL z danego katalogu (do czego nadają się równie dobrze obydwa te narzędzia).