4

I am trying to use the liquibase-hibernate plugin to facilitate db migrations in my Kotlin project. My build.gradle.kts file is configured as follows:

plugins {
    [...]
    id("org.liquibase.gradle") version "2.0.1"
    [...]
}
dependencies {
    [...]
    liquibaseRuntime("org.liquibase:liquibase-core:3.6.2")
    liquibaseRuntime("org.liquibase.ext:liquibase-hibernate5:3.6")
    liquibaseRuntime("org.postgresql:postgresql")
    liquibaseRuntime("org.springframework.boot:spring-boot:2.1.6.RELEASE")
    liquibaseRuntime("org.springframework:spring-orm:5.1.8.RELEASE")
    liquibaseRuntime("ch.qos.logback:logback-classic:1.2.3")

    liquibaseRuntime(sourceSets.getByName("main").output)
    [...]
}
liquibase {
    activities.register("main") {
        this.arguments = mapOf(
                "changeLogFile" to "src/main/resources/db/changelog/db.changelog-master.yaml",
                "referenceUrl" to "hibernate:spring:com.company.product.model.persist?dialect=org.hibernate.dialect.PostgreSQL9Dialect&hibernate.physical_naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy&hibernate.implicit_naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy&hibernate.enhanced_id=true",
                "url" to "jdbc:postgresql://localhost:5432/postgres",
                "username" to "<username>",
                "password" to "<password>",
                "driver" to "org.postgresql.Driver"
        )
    }
    runList = "main"
}

I also have an Address.kt file as follows:

package com.company.product.model.persist

import com.company.product.model.AbstractJpaPersistable
import javax.persistence.CascadeType
import javax.persistence.Entity
import javax.persistence.FetchType

@Entity
class Address(
        val street: String,
        val zipCode: String,
        val city: String
) : AbstractJpaPersistable<Long>()

The issue I am running into is when running the liquibase diff command I am getting the following error:

Unexpected error running Liquibase: Unable to load class [com.company.product.model.persist.Address]

I have verified that in build/classes/kotlin/main/com/company/product/model/persist there is a compiled Address class file.

I have tried every configuration combination I can think of with no luck. I even tried pointing the liquibaseRuntime to files("src/main") as documented by various users on liquibase-hibernate's GitHub page with no luck. Any help is appreciated. Thanks!


Edit

This line is the issue: : AbstractJpaPersistable<Long>().

If I figure out why this is I will post back. In the meantime, here is the code:

package com.company.product.model

import org.springframework.data.domain.Persistable
import org.springframework.data.util.ProxyUtils
import java.io.Serializable
import javax.persistence.GeneratedValue
import javax.persistence.Id
import javax.persistence.MappedSuperclass
import javax.persistence.Transient

/**
 * Abstract base class for entities. Allows parameterization of id type, chooses auto-generation and implements
 * [equals] and [hashCode] based on that id.
 *
 * This class was inspired by [org.springframework.data.jpa.domain.AbstractPersistable], which is part of the Spring Data project.
 */
@MappedSuperclass
abstract class AbstractJpaPersistable<T : Serializable> : Persistable<T> {

    companion object {
        private val serialVersionUID = -5554308939380869754L
    }

    @Id
    @GeneratedValue
    private var id: T? = null

    override fun getId(): T? {
        return id
    }

    /**
     * Must be [Transient] in order to ensure that no JPA provider complains because of a missing setter.
     *
     * @see org.springframework.data.domain.Persistable.isNew
     */
    @Transient
    override fun isNew() = null == getId()

    override fun toString() = "Entity of type ${this.javaClass.name} with id: $id"

    override fun equals(other: Any?): Boolean {
        other ?: return false

        if (this === other) return true

        if (javaClass != ProxyUtils.getUserClass(other)) return false

        other as AbstractJpaPersistable<*>

        return if (null == this.getId()) false else this.getId() == other.getId()
    }

    override fun hashCode(): Int {
        return 31
    }
}
Sloth Armstrong
  • 1,066
  • 2
  • 19
  • 39
  • Had a similar issue, with an entity implementing an interface from a library. Solution was to include the library with `liquibaseRuntime` scope in Gradle. It needs the superclass in the classpath to be able to load the class. – Philipp Nowak Sep 11 '19 at 15:26

0 Answers0