In this tutorial we will see how to setup Liquibase in Spring for multiple datadources. In my previous tutorial we have seen how to setup multiple datadources in Spring Boot application. Here also we will create a Spring Boot application to define multiple datasources and will use these datasources into our Liquibase.

Prerequisites

The following configurations are required in order to run the application
Eclipse
JDK 1.8
Have gradle installed and configured
Spring boot dependencies in build.gradle

You may also like to read:

Evolving Database using Spring Boot and Liquibase

Spring Boot Liquibase Gradle Example

Setting up project

The first step is to create and setup the gradle based Spring Boot project called spring-boot-liquibase-multiple-datasources in Eclipse. Create a gradle based project in Eclipse and update the default generated build script file with the following build script as given below. In the below build script we have added Spring Boot dependencies along with oracle driver and liquibase dependencies. If you want to use other than Oracle database then you need to change the dependency for database driver.

buildscript {
    ext {
        springBootVersion = '1.5.9.RELEASE'
    }
    repositories {
        mavenLocal()
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}

apply plugin: 'java'
apply plugin: 'org.springframework.boot'

jar {
    baseName = 'SpringBootLiquibaseMultipleDataSources'
    version = '0.0.1-SNAPSHOT'
    manifest {
        attributes("Main-Class": "com.jeejava.main.Application")
    }
}

sourceCompatibility = 1.8
targetCompatibility = 1.8

repositories {
    mavenLocal()
    mavenCentral()
}
    
dependencies {
    compile("org.springframework.boot:spring-boot-starter-web:${springBootVersion}")
    compile("org.springframework.boot:spring-boot-starter-data-jpa")
    compile("com.oracle.jdbc:ojdbc7:12.1.0.2")
    compile("org.liquibase:liquibase-core")
}

Now build the blank project, you should be able to build it. If you face any exception related to main class during the project build then create a main class with main method in it and try to build. Notice we have also included separate liquibase configuration files for separate datasource.

DataSources and Liquibase configurations

As a next step declare your two or more datasources into application.properties file under classpath directory src/main/resources. You need to also include separate liquibase configuration files when you want to use separate datasource for separate liquibase.

#datasource 1
spring.datasource.url=jdbc:Oracle:thin:@//<host>:<port>/<service name>
spring.datasource.username=<username>
spring.datasource.password=<password>
spring.datasource.driverClassName=oracle.jdbc.driver.OracleDriver
datasource.primaryLiquibase.liquibase.change-log=classpath:/db/changelog/changelog-master-primary.yaml

#datasource 2
spring.secondaryDatasource.url=jdbc:Oracle:thin:@//<host>:<port>/<service name>
spring.secondaryDatasource.username=<username>
spring.secondaryDatasource.password=<password>
spring.secondaryDatasource.driverClassName=oracle.jdbc.driver.OracleDriver
datasource.secondaryLiquibase.liquibase.change-log=classpath:/db/changelog/changelog-master-secondary.yaml

Changing server default port

We don’t want to start our server on default port, so we need to specify the port we want our server to be started on. We specify the server port using the following line in application.properties file.

#server port
server.port=9999

Creating changelog-master-primary.yaml

Create the below liquibase configuration file – changelog-master-primary.yaml – under classpath directory db/changelog.

databaseChangeLog:
  - changeSet:
      id: selectCountry
      author: Soumitra
      changes:
      - sqlFile:
          dbms: oracle
          encoding: utf8
          endDelimiter: \n/\s*\n|\n/\s*$
          path: liquibase/select-country.sql
          relativeToChangelogFile: true
          splitStatements: true
          stripComments: true

Creating changelog-master-secondary.yaml

Create the below liquibase configuration file – changelog-master-secondary.yaml – under classpath directory db/changelog.

databaseChangeLog:
  - changeSet:
      id: selectRegion
      author: Soumitra
      changes:
      - sqlFile:
          dbms: oracle
          encoding: utf8
          endDelimiter: \n/\s*\n|\n/\s*$
          path: liquibase/select-region.sql
          relativeToChangelogFile: true
          splitStatements: true
          stripComments: true

Creating select-country.sql

Create below select-country.sql file that we want to execute through liquibase when our application starts up. Put this file under classpath directory db/changelog/liquibase. In your real application, you may have more sql files and more complex sql files.

select 1 from country
/

Creating select-region.sql

Create below select-region.sql file that we want to execute through liquibase when our application starts up. Put this file under classpath directory db/changelog/liquibase.

select 1 from region
/

Creating Spring Boot configuration class

Create below Spring configuration class that will provide all configuration beans, such as, for datasource, liquibase etc. Notice how we define multiple beans for multiple datasources and how we attach separate datasource to separate liquibase configuration.

@Configuration
public class DatabaseConfig {
    @Bean
    @Primary
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource primaryDataSource() {
        return DataSourceBuilder.create().build();
    }
    @Bean
    @ConfigurationProperties(prefix = "spring.secondaryDatasource")
    public DataSource secondaryDataSource() {
        return DataSourceBuilder.create().build();
    }
    @Bean
    @ConfigurationProperties(prefix = "datasource.primaryLiquibase.liquibase")
    public LiquibaseProperties primaryLiquibaseProperties() {
        return new LiquibaseProperties();
    }
    @Bean("liquibase")
    public SpringLiquibase primaryLiquibase() {
        return springLiquibase(primaryDataSource(), primaryLiquibaseProperties());
    }
    @Bean
    @ConfigurationProperties(prefix = "datasource.secondaryLiquibase.liquibase")
    public LiquibaseProperties secondaryLiquibaseProperties() {
        return new LiquibaseProperties();
    }
    @Bean
    public SpringLiquibase secondaryLiquibase() {
        return springLiquibase(secondaryDataSource(), secondaryLiquibaseProperties());
    }
    private static SpringLiquibase springLiquibase(DataSource dataSource, LiquibaseProperties properties) {
        SpringLiquibase liquibase = new SpringLiquibase();
        liquibase.setDataSource(dataSource);
        liquibase.setChangeLog(properties.getChangeLog());
        liquibase.setContexts(properties.getContexts());
        liquibase.setDefaultSchema(properties.getDefaultSchema());
        liquibase.setDropFirst(properties.isDropFirst());
        liquibase.setShouldRun(properties.isEnabled());
        liquibase.setLabels(properties.getLabels());
        liquibase.setChangeLogParameters(properties.getParameters());
        liquibase.setRollbackFile(properties.getRollbackFile());
        return liquibase;
    }
}

Creating main class

Create below Spring Boot main class in order to deploy the application into embedded tomcat server.

@SpringBootApplication(scanBasePackages = "com.jeejava")
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

Testing the application

Now run the above main class and you would be able to see the logs similar to below in console:

...
classpath:/db/changelog/changelog-master-primary.yaml: classpath:/db/changelog/changelog-master-primary.yaml::selectCountry::Soumitra: SQL in file liquibase/select-country.sql executed
classpath:/db/changelog/changelog-master-primary.yaml: classpath:/db/changelog/changelog-master-primary.yaml::selectCountry::Soumitra: ChangeSet classpath:/db/changelog/changelog-master-primary.yaml::selectCountry::Soumitra ran successfully in 428ms
...
classpath:/db/changelog/changelog-master-secondary.yaml: classpath:/db/changelog/changelog-master-secondary.yaml::selectRegion::Soumitra: SQL in file liquibase/select-region.sql executed
classpath:/db/changelog/changelog-master-secondary.yaml: classpath:/db/changelog/changelog-master-secondary.yaml::selectRegion::Soumitra: ChangeSet classpath:/db/changelog/changelog-master-secondary.yaml::selectRegion::Soumitra ran successfully in 424ms
...

From the above logs, it is clear that the two sql files have been executed successfully. If you check your DATABASECHANGELOG tables in two different database then you will be able to see one entry per database table for two separate datasource.

That’s all. Hope you got an idea how to setup Liquibase in Spring for multiple datadources

You may also like to read:

Evolving Database using Spring Boot and Liquibase

Spring Boot Liquibase Gradle Example

Thanks for reading.

Tags:

I am a professional Web developer, Enterprise Application developer, Software Engineer and Blogger. Connect me on Roy Tutorials | TwitterFacebook Google PlusLinkedin | Reddit

Leave a Reply

Your email address will not be published. Required fields are marked *