javahibernatequarkusdatabase-migrationliquibase

How to generate Liquibase changelogs with Quarkus using the Liquibase Hibernate extension?


I'm working on a Java application using Quarkus and I'm trying to generate Liquibase changelog files from my JPA entities. Previously, I have successfully used the Liquibase Hibernate extension with Kotlin and Spring Boot to achieve this. Here's a brief overview of what I did with Spring Boot:

  1. Added Liquibase Core and the Liquibase Hibernate 6 extension to my project.
  2. Configured Liquibase in my build.gradle.kts (URL, db user and password, ...).
  3. Used the diff command to generate a new changelog file containing the diff between my entities and the referenced database.

How can I achieve similar functionality in a Quarkus application?

Here is what I have done so far in my Quarkus project:

  1. Project Setup:

    • Created a new Quarkus project.
    • Added the following dependencies in pom.xml:
    <dependencies>
      ...
      <dependency>
        <groupId>io.quarkus</groupId>
        <artifactId>quarkus-hibernate-orm-panache</artifactId>
        <version>${quarkus.platform.version}</version>
      </dependency>
      <dependency>
        <groupId>io.quarkus</groupId>
        <artifactId>quarkus-liquibase</artifactId>
        <version>${quarkus.platform.version}</version>
      </dependency>
      <dependency>
        <groupId>org.liquibase.ext</groupId>
        <artifactId>liquibase-hibernate6</artifactId>
        <version>4.28.0</version>
      </dependency>
    </dependencies>
    
    • Added and configured the Liquibase Maven plugin:
    <plugins>
      ...
      <plugin>
        <groupId>org.liquibase</groupId>
        <artifactId>liquibase-maven-plugin</artifactId>
        <version>4.28.0</version>
        <configuration>
          <driver>oracle.jdbc.driver.OracleDriver</driver>
          <url>jdbc:oracle:thin:@//localhost:1521/ORCLCDB</url>
          <changeLogFile>src/main/resources/db/db.changelog-master.yaml</changeLogFile>
          <username>foo</username>
          <password>bar</password>
          <referenceUrl>hibernate:spring:com.example.myapplication?dialect=org.hibernate.dialect.PostgreSQLDialect&</referenceUrl>
        </configuration>
      </plugin>
    </plugins>
    

    Note: I know I am using the Hibernate Spring connection URL, but I don't know which other Hibernate URL I should use.

  2. Liquibase Configuration:

    quarkus.datasource.db-kind=oracle
    quarkus.datasource.jdbc.url=${DB_HOST:jdbc:oracle:thin:@//localhost:1521/ORCLCDB}
    quarkus.datasource.username=${DB_USER:foo}
    quarkus.datasource.password=${DB_PASSWORD:bar}
    quarkus.hibernate-orm.database.generation=none
    quarkus.liquibase.migrate-at-start=true
    
  3. Defined my JPA entities. For example:

    package com.example.foo.repository;
    
    ...
    
    @Entity
    public class Person {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
        private String name;
    
        // Getters and setters
    }
    

However, I haven't found a way to generate the Liquibase changelog files from my JPA entities within the Quarkus ecosystem, like I did with Spring Boot.

Is there a way to generate Liquibase changelog files from JPA entities in Quarkus using the Liquibase Hibernate extension, or is there an alternative approach I should consider?


Solution

  • There is no direct way of doing this, but answer is it's tricky but yes you can achieve it. It's not very neat but close to a working solution.

    You can also check certain discussions in Quarkus Github as well as Liquibase-hibernate issues here and here

    In my ecosystem I use gradle.

    configurations {
        compileOnly {
            extendsFrom annotationProcessor
        }
        liquibase
        liquibaseRuntime.extendsFrom runtime
    }
    
    ext {
        diffChangeLogVersion = "CHANGE-0002"
        rollbackTagVersion = "CHANGE-0002"
        diffChangeLogFile = "src/main/resources/XXXX/db-changelog-${diffChangeLogVersion}.oracle.sql"
        entitiesPackage =  XXX.XXX.XXX.XXX"
        hibernateGenericDialect = "org.hibernate.dialect.OracleDialect"
        springCoreVersion = "6.1.2"
        springDataVersion = "3.2.1"
    }
    
    dependencies {
        // Liquibase
        implementation "io.quarkus:quarkus-liquibase"
        liquibaseRuntime "org.liquibase.ext:liquibase-hibernate6:4.30.0"
        //liquibaseRuntime "org.liquibase:liquibase-groovy-dsl:3.0.2"
        liquibaseRuntime "info.picocli:picocli:4.7.5"
        liquibaseRuntime "com.oracle.database.jdbc:ojdbc11-production:23.2.0.0"
        liquibaseRuntime "javax.xml.bind:jaxb-api:2.3.1"
        liquibaseRuntime "ch.qos.logback:logback-core:1.2.9"
        liquibaseRuntime "ch.qos.logback:logback-classic:1.2.9"
    
        liquibaseRuntime "org.springframework:spring-core:${springCoreVersion}"
        liquibaseRuntime "org.springframework.data:spring-data-jpa:${springDataVersion}"
        liquibaseRuntime "org.springframework.data:spring-data-envers:${springDataVersion}"
        liquibaseRuntime sourceSets.main.output
    }
    
    task deleteDiffChangeLog(type: Delete) {
        delete diffChangeLogFile
    }
    
    task liquibaseEntitiesToDbDiffChangelog(type: JavaExec) {
        dependsOn deleteDiffChangeLog
        group = "liquibase"
        classpath sourceSets.main.runtimeClasspath
        classpath configurations.liquibaseRuntime
        mainClass = "liquibase.integration.commandline.LiquibaseCommandLine"
        args "--logLevel=FINE"
        args "--changeLogFile=${diffChangeLogFile}"
        args "--url=${dbURL}"
        args "--username=${dbUser}"
        args "--password=${dbPassword}"
        args "--defaultSchemaName=${dbSchema}"
        args "--driver=${dbDriver}"
        args "--referenceUrl=hibernate:spring:${entitiesPackage}?dialect=${hibernateGenericDialect}"
        args "diffChangeLog"
    }