Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to divide Liquibase package structure for dev and prod environment in Spring Boot?

My package structure is looks like:

enter image description here

In /db.changelog/db.changelod-master.xml i include /db.changelog/v1/db.changelog-1.0.xml where i also include all changelogs from /db.changelog/v1/changeset package.

In my application, I have two profiles: dev and prod, and I need to divide the structure of packages according to "Best Practises" of Liquibase. Some changelogs can be in prod and dev environment.

Also, I can use context attribute in changeset tag and explicitly set dev or prod value, but this workaround is not preferable.

Simple usage looks like: i switch to prod profile and some tables will not be created or some inserts to Database will be skipped.

Can you please help me refactor structure of packages according to Liquibase "Best Practices??

like image 309
Abzelhan Avatar asked Oct 04 '18 11:10

Abzelhan


People also ask

What is Databasechangelog?

Liquibase Concepts Simply put – a changelog contains an ordered list of changesets, and a changeset contains a change. You and your team can specify database changes in one of four different changelog formats: SQL, XML, JSON, or YAML. And, you can even mix and match different types of changelogs, if desired.

What is runOnChange Liquibase?

The runOnChange changeset attribute runs the change the first time it is detected and each time the changeset is modified. Liquibase determines that a changeset has been modified by comparing the MD5 checksum for the changeset to the checksum stored in the DATABASECHANGELOG table.


1 Answers

Solution1:
You need to define 'liquibase.contexts' property into your yaml file. Something like below.

spring:
  profiles: dev
  datasource:
    url: jdbc:postgresql://localhost:5432/dev
    username: postgres
    password: password
    driver-class-name: org.postgresql.Driver
liquibase:
   contexts: dev

After adding this the below change set will only execute when your local profile is 'dev' (i.e. spring-boot:run -Dspring.profiles.active=dev)

<changeSet id="20161016_my_first_change2" author="krudland" context="dev">
    <sql>
        insert into customer (firstname, lastname) values ('Franklin','Ike');
    </sql>
    <rollback>
        delete from customer where firstname = 'Franklin' and lastname = 'Ike';
    </rollback>
</changeSet>

Solution2:
If you don't want to use liquibase.context, You might can use maven to filter recourses : The key was to use the maven filter element in conjunction with the resource element as explained in Liquibase Documentation.

Also it's important to include the resources goal in the maven command:

mvn resources:resources liquibase:update -Plocal

This is the file hierarchy I used:

|-- pom.xml
`-- src
    `-- main
       |-- resources
       |   `-- liquibase.properties
       |   |-- changelog
       |       `-- db-changelog-master.xml
       |       `-- db-changelog-1.0.xml
       |-- filters
           |-- local
           |   `-- db.properties
           |-- dev
           |   `-- db.properties

The db.properties file would look like the following:

database.driver = oracle.jdbc.driver.OracleDriver
database.url = jdbc:oracle:thin:@<host_name>:<port_number>/instance
database.username = user
database.password = password123
database.changelogfile = db.changelog-master.xml

The liquibase.properties file would look like the following:

changeLogFile: changelog/${database.changelogfile}
driver: ${database.driver}
url: ${database.url}
username: ${database.username}
password: ${database.password}
verbose: true

The POM file would look like the following:

<build>
      <pluginManagement>
         <plugins>
            <plugin>
               <groupId>org.liquibase</groupId>
               <artifactId>liquibase-maven-plugin</artifactId>
               <version>3.1.0</version>
               <configuration>
                  <propertyFile>target/classes/liquibase.properties</propertyFile>
               </configuration>
            </plugin>
         </plugins>
      </pluginManagement>
   </build>


<profiles>
    <profile>
        <id>local</id>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
        <build>
            <filters>
                <filter>src/main/filters/local/db.properties</filter>
            </filters>
            <resources>
                <resource>
                    <directory>src/main/resources</directory>
                    <filtering>true</filtering>
                </resource>
            </resources>
        </build>
    </profile>
    <profile>
        <id>dev</id>
        <build>
            <filters>
                <filter>src/main/filters/dev/db.properties</filter>
            </filters>
            <resources>
                <resource>
                    <directory>src/main/resources</directory>
                    <filtering>true</filtering>
                </resource>
            </resources>
        </build>
    </profile>
</profiles>
like image 159
M-Razavi Avatar answered Nov 09 '22 17:11

M-Razavi