Multi-Tenancy Support for Liquibase
I wrote about multi-tenancy with JPA and noticed that Hibernate does not support ddl-export with more than one datasource or schema. Fair enough — if you’re running complex scenarios like this, you usually rely on something more sophisticated like Liquibase or Flyway.
My personal favourite is Liquibase and its Spring integration already features support for multi-tenancy with schema separation as well as datasource separation. There is also a CDI integration, which nicely fits Java-EE environments — but compared to the Spring version it’s quiet basic.
I tried to extend it: there are some hooks you can use to do stuff before and after liquibase runs, but I didn’t manage to get it to run more than once. As it’s not much code I decided to reimplement it. The original version is implemented as CDI extension, as it targets CDI 1.0 environments. Most of the code is actually boilerplate to do the lifecycle integration. I went for CDI 1.1, which already has lifecycle events built in (using the @Initialized
qualifier) so I only needed to do the actual liquibase stuff. Currently, it only supports schema-separation.
You can find the code on github: https://github.com/gtudan/liquibase-cdi-multitenancy
All you need to do is add the library as dependency and create a class in your project that extends CDILiquibaseConfig
. Here’s an example that I used in the integration tests:
I created the datasource myself in the example, but you could also inject yours with the @Resource
annotation.
This will spin up a liquibase instance during the deployment that parses the changelog and executes it against all given schemas. Each schema will get it’s own database_changelog
table, so more tenants can be added later on.
All schemas will be updated sequentially. I experimented with doing it in parallel, but figured out that parsing the changelog and calculating the checksums took most of the time. So I decided to do this just once and reuse the liquibase instance for all tenants. This might get into the way of some of the more advanced liquibase features (like parameters, as they go into the checksum calculation), but as long as you don’t have any tenant-specific changes you should be fine.
There’s still quiet a few things that could be improved, like adding support for datasource-separation, but all the features from the current liquibase integration are there. Let me know what you think and pull requests are always welcome!