w , , ,

FajneFajne Dobre!Dobre! ŚwietnieŚwietnie

Liquibase – zarządzanie zmianami w bazach danych

Liquibase jest otwartą biblioteką służącą do śledzenia, zarządzania i stosowania zmian w schematach baz danych. Stanowi ono prawdopodobnie najpopularniejsze narzędzie do wersjonowania baz danych w projektach komercyjnych.

Przykład wykorzystania Liquibase

Załóżmy, że mamy dwie instancje tworzonej aplikacji – wersja produkcyjna, oraz wersja developerska. W przypadku uruchomienia aplikacji w wersji developerskiej Liquibase generuje schemat bazy danych oraz dane testowe. W przypadku wersji produkcyjnej pozostaje przy samym schemacie. Takie działanie pozwala na sterowanie działaniami w zależności od uruchomionej instancji. Do realizacji tego zadania potrzebna jest znajomość definiowania profili w Spring.

Najprostsza implementacja

Tworzymy projekt w Spring Boot i dodajemy zależność Liquibase:

<dependency>
    <groupId>org.liquibase</groupId>
    <artifactId>liquibase-core</artifactId>
</dependency>

W pierwszej kolejności należy zdefiniować plik konfiguracyjny dla Liquibase. Można może on mieć format XML, JSON, YAML. W tym przykładzie posłużę się XML. Jego szablon powinien wyglądać w tej sposób:

<databaseChangeLog
        xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
        xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd
    http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd">
</databaseChangeLog>

W tym momencie nic on nie realizuje, definiuje on tylko przestrzeń nazw do wykorzystania.
Następnie w pliku konfiguracyjnym Spring Boot application.properties podajemy ścieżkę do katalogu w jakim został on utworzony. W moim przypadku jest to:
spring.liquibase.change-log=classpath:/db/changelog/dbchangelog.xml

Teraz można zdefiniować kolejny plik, który odpowiada za tworzenie schematu bazy danych. Dobrą praktyką jest, aby tworzyć plik per modyfikacja. Czyli w tym przypadku pierwszy plik będzie odpowiadał za tworzenie bazy danych, drugi za dodawanie rekordów.

Tworzenie tabeli

Tworze nowy plik o dowolnej nazwie np. addPerson.xml. Następnie wypełniam go następującym kodem:

<databaseChangeLog
        xmlns="http://www.liquibase.org/xml/ns/dbchangelog/1.7"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog/1.7
         http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-1.7.xsd">

    <changeSet id="1" author="byku">
        <createTable tableName="person">
            <column name="address" type="varchar(255)"/>
        </createTable>
    </changeSet>
</databaseChangeLog>

Jest tu zwarta przestrzeń nazw a dodatkowo utworzona struktura tabeli. Znacznik changeSet zawiera informacje o numerze zmiany (później do czego to może się przydać), oraz nazwę autora. Następnie z wykorzystaniem znaczników XML tworzona jest baza danych z jedną kolumną adress.
Składnia jest intuicyjna, lecz wymaga drobnego przyswojenia. Spis całej składni i dostępnych operacji znajdziesz tutaj:
https://www.liquibase.org/documentation/changes/index.html
Teraz wystarczy w głównym pliku konfiguracji Liquibase wskazać namiary do pliku addPerson.xml:

<databaseChangeLog
        xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
        xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd
    http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd">

    <include file="version/personTable.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

Ja jeszcze wskazałem relativeToChangelogFile, po to, aby mieć możliwość podawania ścieżki relatywnej względem pliku z konfiguracją.

Dodawanie rekordów

Należy stworzyć analogiczny plik addPerson.xml i dodać w nim dodawanie kolumny zgodnie z dokumentacją Liquibase:

<databaseChangeLog
        xmlns="http://www.liquibase.org/xml/ns/dbchangelog/1.7"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog/1.7
         http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-1.7.xsd">
    <changeSet author="byku" id="2">
        <insert schemaName="public"
                tableName="person">
            <column name="address" value="Jana Pawła II" type="varchar(255)"/>
        </insert>
    </changeSet>
</databaseChangeLog>

Oczywiście następnie trzeba dodać nowy wpis w pliku konfiguracyjnym Liquibase:

<include file="version/addPerson.xml" relativeToChangelogFile="true"/>

Profile

Aby lepiej zobrazować moc Liquibase utworze dwa profile zgodne z treścią przykładu jaki został opisany w nagłówku „Przykład wykorzystania”.
Tworze dwa pliki konfiguracyjne dla Spring Boot (prod i dev):

application-prod.properties
spring.datasource.url=jdbc:h2:file:./databaseProd
spring.h2.console.enabled=true
spring.h2.console.path=/console
spring.liquibase.change-log=classpath:/db/changelog/dbchangelog-prod.xml
server.port=8082
application-dev.properties
spring.datasource.url=jdbc:h2:file:./databaseDev
spring.h2.console.enabled=true
spring.h2.console.path=/console
spring.liquibase.change-log=classpath:/db/changelog/dbchangelog-dev.xml
server.port=8081

Różnią się one portami (abym mógł uruchomić obie na jednej maszynie) oraz ścieżkami do pliku konfiguracyjnego Liquibase. Jeden posiada includa tylko do personTable.xml drugi natomiast personTable.xml i addPerson.xml.

Uruchomienie

Teraz zauważymy uruchamiając aplikacje z flagą

-Dspring.profiles.active=prod

lub

-Dspring.profiles.active=dev

Włączona zostanie aplikacja produkcyjna ze sama tabelą albo developerska z dodatkowym rekordem.

Co ląduje w bazie?

Zawartość produkcyjnej bazy danych
Zawartość developerskiej bazy danych
Liquibase tworzy dodatkową tabelę w której umieszcza informacje na temat zaimportowanych elementów

Dodatkowe materiały na temat Liquibase

Zachęcam Cię do obejrzenia wido w którym krok po kroku pokazuje implementacje i inne możliwości tej biblioteki 😊

Link do projektu na GitHub:
https://github.com/bykowski/springboot-liquibase

Napisane przez Przemysław Bykowski

Aktywny programista i energiczny trener. Specjalizuje się w Spring Boot i uczę go w ramach AkademiaSpring.pl. Po godzinach udzielam się na YouTubach. Więcej o mnie.

Dodaj komentarz

Spring Data – Tworzenie aplikacji z wykorzystaniem Hibernate 5 [Szkolenie]

Spring Boot

Spring Boot #24 – Budowanie profili konfiguracyjnych