• Skip to primary navigation
  • Skip to main content
  • Skip to primary sidebar

Thoughts on Java

  • Tutorials ▼
    • Hibernate & JPA Tutorials
    • Hibernate Tips
    • Tutorials on YouTube
  • Books & Courses ▼
    • Hibernate Tips Book
    • Online Training
    • Open Workshops
    • On-Site Training
  • Consulting ▼
    • Consulting Call
    • Project Coaching
  • About ▼
    • About Thoughts on Java
    • Support Thoughts on Java
    • Resources
  • Member Library
You are here: Home / Database Migration / How To Implement Automatic Database Updates By Integrating Liquibase
Do you live in Europe?
Then I hope to see you at one of my in-person workshops in December 2019. You will learn to use Hibernate advanced features and to improve the performance of your persistence layer.

How To Implement Automatic Database Updates By Integrating Liquibase

By Thorben Janssen 1 Comment

  • tweet 
  • share 
  • share 
  • share 
  • share 
  • email 


After I talked about how to add Liquibase to your project and how to update your database together with your application code, it’s time to integrate Liquibase into your application so that you can execute the update automatically. Special thanks to Carlos Feria who asked for this post in a comment.

The automatic execution of the update scripts is especially interesting when you build smaller applications that don’t run in a highly regulated enterprise environment. In these situations, it’s often not possible to run the update process yourself and there might be no operations team which executes the SQL scripts. So, you need to run the database update automatically when you start your application.

There are several ways to do that. If you’re building a plain Java application, you can use the Liquibase API to trigger the update. And it gets even easier, if you’re using a CDI container, e.g. in a Java EE application server, or Spring. I will show you all 3 approaches in this post.

Let’s start with the plain Java environment.

Don’t want to read? You can watch it here!

Follow me on YouTube to not miss any new videos.



Already a member? Login here.


 

Run Liquibase as part of a Java SE application

Before you can use the Liquibase API, you need to add the required dependencies to your application. The following maven coordinates add the Liquibase core component in version 3.5.3 to your project.

<dependency>
	<groupId>org.liquibase</groupId>
	<artifactId>liquibase-core</artifactId>
	<version>3.5.3</version>
</dependency>

After you’ve done that, you can implement the database migration in 3 steps:

  1. Get a database connection
  2. Initialize Liquibase
  3. Run the update

 

Integrate Liquibase into Hibernate’s bootstrapping process

Getting the database connection obviously depends on your environment and technology stack. In this post, I will show you how to do that with Hibernate 5.

Bootstrapping Hibernate

Follow me on YouTube to not miss any new videos.

If you’re using Hibernate, you already configured the database connection in your Hibernate configuration. You probably also want to use Hibernate’s database validation to make sure that your mapping fits the database. You can do that by adding Liquibase to your startup process and execute the update before you create a SessionFactory.

// Prepare the Hibernate configuration
StandardServiceRegistry reg = new StandardServiceRegistryBuilder().configure().build();
MetadataSources metaDataSrc = new MetadataSources(reg);

// Get database connection
Connection con = metaDataSrc.getServiceRegistry().getService(ConnectionProvider.class).getConnection();
JdbcConnection jdbcCon = new JdbcConnection(con);

// Initialize Liquibase and run the update
Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(jdbcCon);
Liquibase liquibase = new Liquibase("db.changelog.xml", new ClassLoaderResourceAccessor(), database);
liquibase.update("test");

// Create Hibernate SessionFactory
sf = metaDataSrc.addAnnotatedClass(Author.class).addAnnotatedClass(Book.class).buildMetadata().buildSessionFactory();

You first need to build a StandardServiceRegistry and use it to instantiate a MetadataSources object. I don’t provide any configuration when calling these methods and Hibernate reads the hibernate.cfg.xml file from the classpath.

In the next step, you can use the MetadataSources object to get an instance of a ConnectionProvider service and retrieve a java.sql.Connection. Hibernate created this connection based on the configuration data in the hibernate.cfg.xml file. You can then use the Connection object to create a Liquibase-specific JdbcConnection.

Now you’ve everything you need to initialize Liquibase. You first need to create a Database object and provide the name of the changelog file, a ClassLoaderResourceAccessor instance and the database object. Then, you can call the update method with a reference to the context you want to use for your database update.

After you’ve updated your database, you can follow Hibernate’s standard bootstrapping process. You therefore use the MetadataSources object to build your MetaData and build a SessionFactory.

That’s all you need to do to integrate Liquibase into your Java SE application. Every time you start the application, Liquibase will check the database and perform the required updates.

 

Run Liquibase with Spring Boot

Integrating Liquibase into your Spring Boot application is extremely easy. You just have to add the Liquibase Core to your classpath.

<dependency>
	<groupId>org.liquibase</groupId>
	<artifactId>liquibase-core</artifactId>
	<version>3.5.3</version>
</dependency>

That’s all you need to do. The Liquibase integration will automatically load the master changelog file from db/changelog/db.changelog-master.yaml.

 

Run Liquibase with a CDI container

The CDI integration is also a lot easier than integrating Liquibase into a plain Java SE application. But it requires a little more work than the Spring Boot integration.

You need to add the following 2 dependencies to your project and include them in your deployment.

<dependency>
	<groupId>org.liquibase</groupId>
	<artifactId>liquibase-core</artifactId>
	<version>3.5.3</version>
</dependency>
<dependency>
	<groupId>org.liquibase</groupId>
	<artifactId>liquibase-cdi</artifactId>
	<version>3.5.3</version>
</dependency>

After you’ve done that, you need to implement a CDI bean with 3 producer methods. These methods need to provide a CDILiquibaseConfig, a DataSource and a ResourceAccessor.

As you can see in the following code snippet, the produced CDILiquibaseConfig object contains a reference to the master changelog file. So, please make sure that you reference a file within your deployment unit or that you use an external path which you can access from within the CDI container on all machines. I explained the content of this file in more details in the first and second post of this series.

@Dependent
public class LiquibaseCdiIntegration {

    @Resource
    private DataSource myDataSource;

    @Produces 
    @LiquibaseType
    public CDILiquibaseConfig createConfig() {
        CDILiquibaseConfig config = new CDILiquibaseConfig();
        config.setChangeLog("//c:/tmp/db.changelog.xml");
        return config;
    }

    @Produces 
    @LiquibaseType
    public DataSource createDataSource() throws SQLException {
        return myDataSource;
    }

    @Produces 
    @LiquibaseType
    public ResourceAccessor create() {
        return new ClassLoaderResourceAccessor(getClass().getClassLoader());
    }
}

That’s all you need to do. When you deploy this application into a CDI container, Liquibase will run during the deployment and update the database.



Already a member? Login here.


 

Summary

As you’ve seen in this post, you can integrate Liquibase into your application. Doing that allows you to automatically check and update the database every time you start your application.

  • tweet 
  • share 
  • share 
  • share 
  • share 
  • email 
Become a Thoughts on Java Supporter to claim your member perks and to help me write more articles like this.

Filed Under: Database Migration

Improve Your Hibernate Skills At An In-Person Workshop

Implement Your Persistence Layer with Ease

Learn More About Hibernate

Need Some Help with Your Project?

Reader Interactions

Leave a Reply Cancel reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Primary Sidebar

Join over 10.000 developers
in the
Thoughts on Java Library

Ebooks Sidebar Get free access to ebooks, cheat sheets and training videos.
Join Now!
Don't like ads?
Become a Thoughts on Java Supporter.
Special Launch Price

Let’s Connect


Thorben Janssen
Independent consultant, trainer and author
  • Facebook
  • GitHub
  • LinkedIn
  • Twitter
  • xing
  • YouTube

Speaking at

2nd-3rd December 2019
Düsseldorf (Germany):
Advanced Hibernate Workshop (2-day Workshop - English)

4th-6th December 2019
Düsseldorf (Germany):
Hibernate Performance Tuning Workshop (3-day Workshop - English)

Looking for an on-site training?

Featured Post

14 YouTube Channels You Should Follow in 2019

Getting Started With Hibernate

Entities or DTOs – When should you use which projection?

Ultimate Guide – Association Mappings with JPA and Hibernate

Ultimate Guide to JPQL Queries with JPA and Hibernate

Recent Posts

  • Don’t expose your JPA entities in your REST API
  • Hibernate Tip: How to control cache invalidation for native queries
  • Hibernate Tip: How to customize the association mappings using a composite key
  • Hibernate Tip: How to integrate an external query builder
  • Hibernate Tip: Best Way To Work with Scalar Projections
  • 6 Hibernate Mappings You Should Avoid for High-Performance Applications
  • Hibernate Tip: Best Way To Work with Scalar Projections
  • Using the Optimal Query Approach and Projection for JPA and Hibernate
  • Implementing the Outbox Pattern with CDC using Debezium
  • Hibernate Tip: Difference between @JoinColumn and @PrimaryKeyJoinColumn
Don't like ads?
Become a Thoughts on Java Supporter.

Copyright © 2019 Thoughts on Java

  • Impressum
  • Disclaimer
  • Privacy Policy