Flyway Nedir

Flyway bir migration ve sürüm kontrol aracıdır.

  • Java API, komut satırı clienti, Maven ve Gradle eklentisi var.
  • MySQL, PostgreSQL, SQL Server ve Oracle gibi ilişkisel veritabanlarının çoğunu destekler.
  • Migration komut dosyaları bir SQL veya Java ile yazılmıştır.

Spring Boot, javax.sql.DataSource, JPA ve Hibernate, Flyway ve Liquibase gibi çeşitli mekanizmalarla uygulama başlangıcında veritabanı migrationu otomatik olarak çalıştırabilir.

Bu yazımda, size Spring Boot’de Flyway kullanımı ile ilgili örnek yapacağım.

Spring Boot Flyway Örneği

Spring Bootda Proje Oluşturma

Yapacağım örnekte ben database olarak mysql kullanacağım.

Localimde çalışan mysql olmadığı için mysql docker üzerinden kuracağım.

Spring initalizryi kullanarak group idsi com,artifact idsi spring-boot-flyway ve paket ismi flyway olan spring boot projesi oluşturalım.

Dependecy olarak Lombok,Spring Web,Spring Data Jpa,Spring BootActuator ,Mysql,Flyway Migrationu bağımlılıklarını projeye ekleyelim.

Son olarak proje adını spring-boot-flyway yapalım ve finish diyerek projemizi oluşturalım.

Proje dizin yapısı aşağıdaki gibi olmalıdır.

Projenize Flywaye Ekleme

Flyway’i projenize pom.xml veya build.gradle dosyasına bağımlılık olarak ekleyebilirsiniz.Kütüphane versiyonları Maven Central Repositoryde bulunur.

Bir Spring Boot projesinde Flyway kullanıyorsanız, Spring Boot bağımlılık sürümü otomatik olarak çözecektir.

<dependency> <groupId>org.flywaydb</groupId> <artifactId>flyway-core</artifactId>
</dependency>

Flyway migration durumunu ve geçmişini web arayüzü üzerinden sorgulamakiçin Spring Boot Web’e ve Actuatora de ihtiyacınız olabilir.

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

Biz bu bağımlılıkları zaten projemizi oluşturuken eklemiştik.

Yalnızca tek bir migration mekanizması kullanmanız önerilir

Birden çok migration mekanizmasının kullanılması kafa karışıklığına ve yönetilmesi zor olabilir, bu nedenle Flyway’i kullanırken diğer migration toollarını devre dışı bırakmak iyi bir uygulamadır.

Spring Boot, JPA ve Hibernate aracılığıyla, şema DDL’i @Entity sınıflarındaki tanımınızla veritabanından otomatik olarak export edilebilir.

spring.jpa.hibernate.ddl-auto değerini validate yada none ile kapatarak bu özelliği devre dışı edebiliriz.(gömülü olmayan databaselerde bu değer varsayılan nonedir)

Spring Boot,DataSourcemuzdaki classpath:schema.sql ve classpath:data.sql dosyaları otomatik olarak çalıştırabilir.Bu özellik spring.datasource.initialization-mode Propertisi üzerinden kontrol edilebilir.Bu propertinin default değeri embedded dir(yalnızca gömülü veritabanları için geçerlidir).

Flyway Migration Komut Dosyaları

JPA ve Hibernate’den farklı olarak, Flyway’deki veritabanı migrationu, @Entity sınıflarının tanımına dayanmaz, Migration komut dosyalarını SQL veya Java’ya manuel olarak yazmanız gerekir, SQL en sık kullanılan kullanımdır.

Genellikle, SQL komut dosyaları V<VERSION>__<DESCRIPTION>.sql biçimindedir.

<VERSION>’1.0′ veya ‘1_1’ gibi bir nokta veya alt çizgi ile ayrılmış sürüm numarısıdır).<VERSION>unique olmalı.

<DESCRIPTION>Her migrationun ne yaptığını hatırlayabilmeniz için açıklama olmalı.

Aşağıdaki bazı örnek oluşturduğum SQL scriptlerini paylaştım.

Resource dizininde db içerisindeki migration dizinide aşağıdaki sql dosyalarını migration klasörünün içerisine koyun.

V1.0__create_book.sql

CREATE TABLE `book` (`id` int(11) NOT NULL AUTO_INCREMENT, `description` varchar(255) DEFAULT NULL, `title` varchar(255) DEFAULT NULL, PRIMARY KEY(`id`)) ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8;

V1.1__insert_book.sql

INSERT INTO `book` (`title`, `description`) VALUES('Hello Koding', 'Coding tutorials series');

Varsayılan olarak, Spring Boot migration scriptleri classpath:db/migration klasöründe arar, spring.flyway.locations propertisi ile bu konumu değiştirebilirsiniz.

Flyway nasıl çalışır?

Flyway, migration script dosya adında belirtilen sürüm numarasına göre, komut dosyalarını sırasıyla temel alınan veritabanına uygular.

Her yürütmede, yalnızca bekleyen migrationlar uygulanır.Flyway bu işlemi tablo yoksa (varsa) oluşturarak ve bir veri tablosu güncelleyerek yönetir.

Migration komut dosyaları uygulandıktan sonra değiştirilemez.Flyway, her uygulamadaki her scriptin checksum toplamını karşılaştırır ve bir uyumsuzluk varsa exception fırlatır.

Flyway Veri Kaynağını Yapılandırma

Spring Boot, Flyway’i temel alınan veri kaynağına bağlamak için ek anatasyonlar veya external propertiesler kullanır.

  • @Primary DataSource veya @FlywayDataSource Anatasyonu
  • spring.datasource.[url, username, password] veya spring.flyway.[url, user, password] propertileri

Spring Boot, Flyway’i nasıl çalıştırır?

Spring Boot otomatik olarak, projeye Flyway core kütüphanesini eklediğinizde uygulama açılışında Flyway’i etkinleştirir ve tetikler.Eğer bu ayarı kapatmak istiyorsanız spring.flyway.enabled propertiesini false yapın.( bu propertinin varsayılan değeri true)

Migration sırasında Flyway tarafından atılan herhangi bir exception (önceki bölümde belirtilen migration scriptlerinin checksum uyumsuzluğu hatası gibi) varsa uygulama başlatma işlemi başarısız olabilir.

Her migration script tek bir transactionla çalıştırılır. tüm bekleyen migrationları tek bir transactionla çalıştırmak için spring.flyway.group=true propertisini atayın.(spring.flyway.group varsayılan değeri falsedir).

Mysqli Docker İle Çalıştırma

Benim localimde mysql server olmadığı için mysqli docker üzerinden kuracağım.Mysqli docker üzerinde çalıştırabilmek için docker ve docker-compose bilgisayarınızda yüklü olmalıdır.

Projenin root dizininde docker-compose.yml isimli bir dosya oluşturalım.

docker-compose.yml

version: '3'
services: mysql: container_name: mysql image: mysql:8.0.16 environment: MYSQL_DATABASE: test MYSQL_USER: root MYSQL_ROOT_PASSWORD: root MYSQL_ROOT_HOST: '%' ports: - 3306:3306 command: mysqld --lower_case_table_names=1 --skip-ssl --character_set_server=utf8mb4 --explicit_defaults_for_timestamp restart: always tty: true # volumes: # - ./data:/var/lib/mysql

Kulanıcı adı ve şifresi root olan test isimli bir database oluşturduk.

Projemizin root dizininde docker-compose up -d komutunu çalıştırarak mysql serveri localimizde oluşturalım.

Mysql başarılı bir şekilde localimizde oluşturuldu.Test databasesine localhostdaki 3306 portundan ulaşabilirsiniz.

Model Katmanını Oluşturma

flyway paketi içerisinde model adlı bir paket oluşturalım.Bu model paketinin içerisinde Book adlı bir class oluşturalım.

@Data
@Entity
public class Book { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; private String title; private String description;
}

Repository Katmanını Oluşturma

flyway paketi içerisinde repository adlı bir paket oluşturalım.Bu repository paketinin içerisinde BookRepository adlı bir interface oluşturalım.

public interface BookRepository extends JpaRepository
<Book, Integer> { }

Book modelimiz üzerinden temel crud işlemlerini yapabileceğimiz BookRepositorysınıfımız hazır.BookRepository sınıfı runtime da otomatik olarak inject edilecektir.

flyway paketi içerisinde bootstrap adlı bir paket oluşturalım.Bu bootstrap paketinin içerisinde DataLoader adlı bir class oluşturalım.

@Slf4j
@RequiredArgsConstructor
@Component
public class DataLoader implements ApplicationRunner { private final BookRepository bookRepository; @Override public void run(ApplicationArguments args) throws Exception { log.info(bookRepository.findAll().toString()); }
}

Migration ile oluşturduğumuz dataları,logladık.

application .propertiese loglama ile ilgili aşağıdaki ayarları ekleyelim.

# logging level
logging.level.org.springframework=ERROR
logging.level.flyway=DEBUG
logging.pattern.console=%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n

Uygulamamızı mysqle bağlamak için application.propertiese aşağıdaki ayarları girelim.

#mysql
spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

Tabloyu migration üzerinden oluşturacağımız için aplication.propertiesde hibernate ddl-autoyu validate yapalım.

spring.jpa.hibernate.ddl-auto=validate
spring.jpa.generate-ddl=true
spring.jpa.show-sql=true

Spring Boot Actuator ile web arayüzündeki migration durumunu ve geçmişinietkinleştirmek için application.propertiese aşağıdaki propertiyi ekleyin.

management.endpoints.web.exposure.include=info,health,flyway

{endpoints}/actuator/flyway urlsinden query migration durumunu ve geçmişini görüntüleyebilirsiniz.

Uygulamayı Çalıştırma

Uygulama kullanıma hazır. ./mvnw spring-boot:run komutu ile uygulamamızı çalıştıralım.

Migration başarılı bir şekilde gerçekleşti ve migrationda oluşturduğumuz veri uygulamamızın terminaline basıldı.

Browseri açıp http://localhost:8080/actuator/flyway adresine gidelim.

Bunun dışında veritabanında flyway_schema_history ile tablo sorgulayabilirsiniz.Flyway ile migration durumunu ve geçmişini yönetebilirsiniz.Tabloyu spring.flyway.table(bu property flyway_schema_historyde varsayılandır) ile değiştirebilirsiniz.

Mysql kontenarına bağlanıp mysql -u root -p komutunu girin.

Şifre istecektir.Şifre kısmına root girip mysqle bağlanalım.

Aşağıdaki komutu girerek test databasesine bağlanalım.

Son olarak Migration durumunu ve geçmişini kontrol edelim.

Projenin Github Linki : https://github.com/susimsek/spring-boot-flyway

Slack Kanalımın Linki ;

https://join.slack.com/t/javadevelopercorp58/shared_invite/enQtODM3NzU5NDMzMjA1LWQ1YjFlZGE5MTI0ZDNjZDdlNGE4ZDE4NmM0NTBiODJlMTJiYmZjMjJiZTY3NzI0MTc5ZjJhZmQxN2MyMTlmYjU

Daha fazla konu içeriği ve çeşitliliği istiyorsanız slack kanalımı takip edebilirsiniz.

Responses

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir