Last time I’ve shown how to run Liquibase changesets from Maven and I gave a forecast for an ASAP post about Liquibase and Java. Well, the as soon as possible is more than a month but finally I’m here to show you a simple way to integrate Liquibase in your java application.
The cause of the delay is (as you may see on my GitHub account) that I started to go further into integrating Hibernate and Spring into the System. That one is a bigger work, leads to more posts (hopefully not as delayed as most often) and a fourth part to the Liquibase stories: using Liquibase with Spring (e.g. injecting Liquibase) and get the whole configuration from Java code to a maintainable property file.
First of all, here is the version for the code. It’s a commit for the Liquibase changes with Java. Called first part, but it really is this the only change needed. So I’ll explain the code and go to the other stuff for using Spring.
I had to add two new dependencies to the pom.xml: h2 and liquibase-core. The h2 is needed for the database configuration, and liquibase-core is Liquibase 🙂
I decided to put the connection properties directly into the source code of the application. This is for the ease of the use and for this simple application there is no need for Java Properties. This will come later on because this version is really not maintainable. For the future I’ll make the database connection better maintainable — and from a single location because Hibernate needs a database configuration too. So it is not the best idea to keep database parameters on two separate locations.
Executing the update
First of all we need a java.sql.Connection where the connection data is provided (database url, username and password). From this connection we can move on to Liquibase, create a generic JDBC Connection. This connection is needed to initialize the Database (in this case an H2).
The Liquibase object requires at its creation a reference to the change log xml, a ClassLoaderResourceAccessor to access resources, and the database where the changes are meant to execute. The execution is done with calling the update method. The null parameter is a context for the execution. In this version it is not needed because we only have one database.
Contexts are good in dividing specific changes for specific purposes. For example you have some changes you only want to do on a test system (using version control, continuous delivery, quality assurance systems, etc) and not a production one (I cannot imagine this scenario but however). You could add in your changeset context=”test” and while executing the changeset you can pass the context as parameter to the update method.
Another (and better) scenario is that you have more than one customers who are using the same application but have some unique features which are managed over the database (for example reporting queries). For this you can specify a context for each customer and at the start of the application you can provide this context and execute the changesets only for that customer (or those customers because you can add more than one context to the changeset).
TIP: If you have more than one customer for the same product do not allow DDL changes with context. So you have the same database structure for all customers and don’t get complex database changes as development goes on. You could for example create unit tests which ensure that a DDL changeset does not have a context. Naturally for this you have to forbid a release of your application if a unit test fails. This is a continuous delivery issue — and another best practice.
In the next post (as mentioned above) I’ll integrate Liquibase via Spring into the application (although there is some Hibernate code committed) and discuss that story. That will be much more shorter than Spring integration is way more out-of-the-box than adding Liquibase simple to the app. Eventually I’ll take a peek into the unit test for changesets too (mentioned above) to have a feeling how it goes. And if I have some spare time I’ll add a configuration file (the old liquibase.properties) to the contribution to use that as a configuration source and not the Spring XML file.