Using SpringBoot 3 and Hibernate 6 any generated Liquibase changelogs based on my Java Entity classes are empty

852 Views Asked by At

I have a SpringBoot 3 based Gradle project that uses Hibernate 6 and Liquibase.

The goal is to use the liquibase-hibernate6 dependency to generate an initial Liquibase changelog containing the details of my Java Entity class i.e Item.java.

The problem is that the generated changelog is basically empty.

What is missing in order to generate Liquibase changelog from my Java Entity class?

val liquibaseVersion: String = "4.23.0"
val liquibaseGradlePluginVersion: String = "2.2.0"

plugins {
    java
    war

    id("org.springframework.boot") version "3.1.1"
    id("io.spring.dependency-management") version "1.1.0"
    id("org.liquibase.gradle") version "2.2.0"
}

group = "com.example"
version = "0.0.1-SNAPSHOT"

java {
    sourceCompatibility = JavaVersion.VERSION_17
}

repositories {
    mavenCentral()
}

dependencies {

    implementation("org.postgresql:postgresql:42.6.0")
    implementation("info.picocli:picocli:4.6.3")

    implementation("org.springframework.boot:spring-boot-starter-data-jpa")
    implementation("org.springframework.boot:spring-boot-starter-web")

    implementation("org.liquibase:liquibase-core:$liquibaseVersion")
    implementation("org.liquibase:liquibase-gradle-plugin:$liquibaseGradlePluginVersion")
    implementation("org.hibernate.orm:hibernate-core:6.2.5.Final")
    implementation("org.liquibase.ext:liquibase-hibernate6:$liquibaseVersion")

    implementation("com.fasterxml.jackson.core:jackson-core")
    implementation("com.fasterxml.jackson.core:jackson-databind")
    implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml")

    providedRuntime("org.springframework.boot:spring-boot-starter-tomcat")

    liquibaseRuntime("org.postgresql:postgresql:42.6.0")
    liquibaseRuntime("info.picocli:picocli:4.6.3")
    liquibaseRuntime("org.liquibase:liquibase-core:$liquibaseVersion")
    liquibaseRuntime("org.liquibase.ext:liquibase-hibernate6:$liquibaseVersion")
    liquibaseRuntime("org.hibernate.orm:hibernate-core:6.2.5.Final")
    liquibaseRuntime("org.springframework.boot:spring-boot-starter-data-jpa")
    liquibaseRuntime(sourceSets.getByName("main").output)
}

tasks.withType<Test> {
    useJUnitPlatform()
}

liquibase {
    activities.register("main") {
        this.arguments = mapOf(
            "changelogFile" to "src/main/resources/config/liquibase/changelog/0.1.0/000000_00000000_initial-changelog.xml",
            "url" to "hibernate:spring:com.example?dialect=org.hibernate.dialect.PostgreSQLDialect"
        )
    }
}

I have a Java Entity:

package com.example.demo;

import jakarta.persistence.*;

@Entity
public class Item {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id", nullable = false)
    private Long id;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }
}

Contents of Liquibase changelog after running generateChangeLog via Gradle:

<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd"/>
1

There are 1 best solutions below

0
SimpleJack On

To be honest, i'm wondering why this is even working. Since you're using a Postgres you must provide at least a username. Not quiet sure about password. Can you have a user wihtout a password in Postgres? Anyway... More important, in combination with spring you must point to your package with your Entity classes, as explained here.

Try it again with this updated version of your Gradle file:

plugins {
    // The WAR plugin extends the Java plugin
    id 'war'

    id 'org.springframework.boot' version '3.1.5'
    id 'io.spring.dependency-management' version '1.1.3'
    id 'org.liquibase.gradle' version '2.2.0'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'

java {
    sourceCompatibility = JavaVersion.VERSION_17
}

repositories {
    mavenCentral()
}

dependencies {
    // Web already contains Tomcat as Webserver
    implementation 'org.springframework.boot:spring-boot-starter-web'
    // Data JPA already contains Hibernate
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    
    // jackson-databind has jackson-core as dependency
    implementation 'com.fasterxml.jackson.core:jackson-databind'
    implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-yaml'

    implementation 'org.postgresql:postgresql:42.6.0'
    
    // The Liquibase dependency has to be noted twice: One time for Spring & one time for Liquibase Gradle Plugin
    implementation 'org.liquibase:liquibase-core:4.24.0'
    liquibaseRuntime 'org.liquibase:liquibase-core:4.24.0'
    liquibaseRuntime 'org.liquibase:ext.liquibase-hibernate6:4.24.0'
    liquibaseRuntime 'info.picocli:picocli:4.7.5'
    liquibaseRuntime sourceSets.main.output
}

tasks.named('test') {
    useJUnitPlatform()
}

liquibase {
    activities {
        def springProperties = new Properties()
        file('src/main/resources/application.properties').withInputStream { springProperties.load(it) }
        main {
            url springProperties.getProperty('spring.datasource.url')
            username springProperties.getProperty('spring.datasource.username')
            // Comment the password out, if there is no password
            password springProperties.getProperty('spring.datasource.password')
            // Assumption here: Your entity classes live in the "persistence" package
            referenceUrl "hibernate:spring:${group}.persistence?dialect=org.hibernate.dialect.PostgreSQLDialect"
            changelogFile 'src/main/resources/config/liquibase/changelog/0.1.0/000000_00000000_initial-changelog.xml'
            logLevel 'info'
        }
    }
}

diffChangelog.configure {
    // Keep Java byte code up to date
    dependsOn(compileJava)
}