Java code changeset in liquibase

JavaJdbcLiquibaseFlyway

Java Problem Overview


Is there a way in liquibase to create java code change set (i.e. provide a java class, which will receive a JDBC connection and will perform some changes in the database) ?

(I know that flyway has such feature)

Java Solutions


Solution 1 - Java

Yes, there is such feature. You can create a customChange:

    <customChange class="my.java.Class">
        <param name="id" value="2" />
    </customChange>

The class must implements the liquibase.change.custom.CustomTaskChange interface.

@Override
public void execute(final Database arg0) throws CustomChangeException {
    JdbcConnection dbConn = (JdbcConnection) arg0.getConnection();
    try {
         ... do funny stuff ...
    } catch (Exception e) {
        // swallow the exception !
    }
}

Solution 2 - Java

A complete example will look like this

Create a class that implements CustomTaskChange or CustomSqlChange.

package com.example;

import liquibase.change.custom.CustomTaskChange;
import liquibase.database.Database;
import liquibase.database.jvm.JdbcConnection;
import liquibase.exception.CustomChangeException;
import liquibase.exception.SetupException;
import liquibase.exception.ValidationErrors;
import liquibase.logging.LogFactory;
import liquibase.resource.ResourceAccessor;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class DataLoaderTask implements CustomTaskChange {

	//to hold the parameter value
	private String file;
	

	private ResourceAccessor resourceAccessor;


	public String getFile() {
		return file;
	}

	public void setFile(String file) {
		this.file = file;
	}


	@Override
	public void execute(Database database) throws CustomChangeException {
		JdbcConnection databaseConnection = (JdbcConnection) database.getConnection();
		try {

			//Opening my data file
			BufferedReader in = new BufferedReader(
					new InputStreamReader(resourceAccessor.getResourceAsStream(file)));
			
			//Ignore header
			String str = in.readLine();
		   
			while ((str = in.readLine()) != null && !str.trim().equals("")) {
				LogFactory.getLogger().info("Processing line "+ str);
				//Do whatever is necessary
			}
			in.close();
		} catch (Exception e) {
			throw new CustomChangeException(e);
		}
	}

	@Override
	public String getConfirmationMessage() {
		return null;
	}

	@Override
	public void setUp() throws SetupException {

	}

	@Override
	public void setFileOpener(ResourceAccessor resourceAccessor) {
		this.resourceAccessor = resourceAccessor;
	}

	@Override
	public ValidationErrors validate(Database database) {
		return null;
	}
	
}

In the changeset xml you could use the class as below

<changeSet id="1" author="murali" runAlways="false" failOnError="true" >
		<customChange class="com.example.DataLoaderTask">
			<param name="file" value="/com/example/data/user.csv" />
		</customChange>
</changeSet>

For me the data file is in src/main/resources/com/example/data directory

Hope this helps

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPavel BernshtamView Question on Stackoverflow
Solution 1 - JavapoussmaView Answer on Stackoverflow
Solution 2 - JavaMuraliView Answer on Stackoverflow