简体   繁体   中英

Running liquibase within Java code

For some reason there's no documentation on running liquibase inside Java code. I want to generate tables for Unit tests.

How would I run it directly in Java?

eg

Liquibase liquibase = new Liquibase()
liquibase.runUpdates() ?

It should be something like (taken from liquibase.integration.spring.SpringLiquibase source):

java.sql.Connection c = YOUR_CONNECTION;
Liquibase liquibase = null;
try {
    Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnection(c))
    liquibase = new Liquibase(YOUR_CHANGELOG, new FileSystemResourceAccessor(), database);
    liquibase.update();
} catch (SQLException e) {
    throw new DatabaseException(e);
} finally {
    if (c != null) {
        try {
            c.rollback();
            c.close();
        } catch (SQLException e) {
            //nothing to do
        }
    }
}

There are multiple implementation of ResourceAccessor depending on how your changelog files should be found.

I found a way to achieve setting up the database using either maven or Java. The above example uses FileSystemResourceAccessor() , which unfortunately makes it so that if you deploy an application which needs to set up a database from the jar itself, then you end up having to extract the jar as a zip as a workaround, since these liquibase files exist only in the jar. This means your jar ultimately isn't portable, and you have to have maven wherever you want to set up the database.

Use this structure:

src/main/resources/liquibase/db.changelog-master.xml src/main/resources/liquibase/changelogs/...

Your DB changelog master can look like this:

<?xml version="1.0" encoding="UTF-8"?>
<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">

    <!-- <includeAll path="src/main/resources/liquibase/changelogs"/> -->
    <include file="changelogs/my-date.1.sql" relativeToChangelogFile="true"/>
</databaseChangeLog>

You can use this section for your pom.xml , in order to make sure mvn install will also set up your liquibase DB.

<plugin>
   <groupId>org.liquibase</groupId>
   <artifactId>liquibase-maven-plugin</artifactId>
   <version>3.5.1</version>
   <configuration>
      <changeLogFile>liquibase/db.changelog-master.xml</changeLogFile>
      <driver>org.postgresql.Driver</driver>
      <url>${jdbc.url}</url>
      <username>${jdbc.username}</username>
      <password>${jdbc.password}</password>
   </configuration>
   <executions>
      <execution>
         <phase>process-resources</phase>
         <goals>
            <goal>update</goal>
         </goals>
      </execution>
   </executions>
</plugin>

Use ClassLoaderResourceAccessor() instead of FileSystemResourceAccessor() .

public static void runLiquibase() {

    Liquibase liquibase = null;
    Connection c = null;
    try {
        c = DriverManager.getConnection(DataSources.PROPERTIES.getProperty("jdbc.url"),
                DataSources.PROPERTIES.getProperty("jdbc.username"),
                DataSources.PROPERTIES.getProperty("jdbc.password"));

        Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnection(c));
        log.info(DataSources.CHANGELOG_MASTER);
        liquibase = new Liquibase(DataSources.CHANGELOG_MASTER, new ClassLoaderResourceAccessor(), database);
        liquibase.update("main");
    } catch (SQLException | LiquibaseException e) {
        e.printStackTrace();
        throw new NoSuchElementException(e.getMessage());
    } finally {
        if (c != null) {
            try {
                c.rollback();
                c.close();
            } catch (SQLException e) {
                //nothing to do
            }
        }
    }
}

You can practice with h2-database in test(path "db/changelog.xml" is main/resources/db/changelog.xml):

import liquibase.Contexts;
import liquibase.Liquibase;
import liquibase.database.Database;
import liquibase.database.DatabaseFactory;
import liquibase.database.jvm.JdbcConnection;
import liquibase.exception.LiquibaseException;
import liquibase.resource.ClassLoaderResourceAccessor;
import org.junit.jupiter.api.Test;

import java.sql.DriverManager;
import java.sql.SQLException;

public class LiquidBaseTest {

    @Test
    public void testExecuteLiquidBaseScripts() throws SQLException, LiquibaseException {
        java.sql.Connection connection = DriverManager.getConnection("jdbc:h2:mem:");

        try {
            Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnection(connection));
            Liquibase liquibase = new Liquibase("db/changelog.xml", new ClassLoaderResourceAccessor(), database);
            liquibase.update(new Contexts());
        } finally {
            if (connection != null) {
                connection.rollback();
                connection.close();
            }
        }
    }

}
public static void runLiquibase() throws Exception {
    Map<String, Object> config = new HashMap<>();

    Scope.child(config, () -> {
        try {
            Connection connection = DriverManager.getConnection("your database connection url");
            Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnection(connection));
            Liquibase liquibase = new liquibase.Liquibase("database/db.changelog-main.xml", new ClassLoaderResourceAccessor(), database);
            liquibase.update(new Contexts(), new LabelExpression());
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    });

}

This code will help you to manage a multiple changelogs based on the version and you can provide a reference of main file.

I have followed structure as below.

  • src/main/resources/database/db.changelog-main.xml
  • src/main/resources/database/changelogs/db.changelog-v-1.0.0.xml
  • src/main/resources/database/changelogs/db.changelog-v-1.0.1.xml

A reference link https://docs.liquibase.com/workflows/liquibase-community/using-liquibase-java-api.html

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM