How do I align Spring Boot, Hibernate, Liquibase (via Gradle) constraint naming strategies?

62 views Asked by At

I am trying to get database constraint naming parity between Spring Boot, Hibernate, and Liquibase. We're using Liquibase via the Gradle plugin with the intent of developers being able to run diffChangelog via Gradle and then use those generated contents in our main Liquibase changelogs that Spring Boot will execute. While the Liquibase-generated columns themselves seem to reflect the desired format (snake case), the primaryKeyName seems to be generated as camel case.

For reference this is Spring Boot 3.2.0, Hiberate 6.3.1, Liquibase 4.25.0, Liquibase Gradle plug-in 2.2.0.

Here's what our liquibase Gradle config looks like, where I'm specifying naming strategies in the referenceUrl.

liquibase {
    activities {
        main {
            String targetFile = project.gradle.startParameter.taskNames.contains('liquibaseDiffChangelog') ? "db.changelog.diff.xml" : "/db/changelog/db.changelog-master.xml"
            driver 'org.postgresql.Driver'
            url System.getenv("JDBC_DATABASE_URL") ?: 'jdbc:postgresql://localhost:5432/sbdemo'
            //username 'postgres'
            //password ''
            changelogFile targetFile
            referenceDriver 'liquibase.ext.hibernate.database.connection.HibernateDriver'
            referenceUrl 'hibernate:spring:md.hippo.demo.model' +
                    '?dialect=org.hibernate.dialect.PostgreSQLDialect' +
                    '&hibernate.implicit_naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy' +
                    '&hibernate.physical_naming_strategy=org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy'
        }
    }
}

liquibaseDiff.dependsOn compileJava
liquibaseDiffChangelog.dependsOn compileJava

Here's an example of what diffChangelog creates with this configuration:

    <changeSet author="blah" id="1701708228031-1">
        <createTable tableName="patient">
            <column name="id" type="UUID">
                <constraints nullable="false" primaryKey="true" primaryKeyName="patientPK"/>
            </column>
            <column name="first_name" type="VARCHAR(255)"/>
            <column name="last_name" type="VARCHAR(255)"/>
        </createTable>
    </changeSet>

Note the primary key name vs the column names. I'm not explicitly setting any column names on the entity itself.

Here's what I'm configuring in Spring Boot's application.properties:

spring.jpa.hibernate.naming.implicit-strategy=org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy
spring.liquibase.enabled=true
spring.liquibase.url=jdbc:postgresql://localhost:5432/sbdemo
spring.liquibase.user=postgres
#spring.liquibase.password=
#spring.liquibase.default-schema=
spring.liquibase.change-log=classpath:db/changelog/db.changelog-master.xml

What's interesting is that if I let Spring Boot execute that changelog, the resulting primary key constraint name in the database is patient_pkey, however if I were to execute liquibase update via Gradle it would create the key name as it exists in the changelog file, so patientPK.

Ideally I would like Liquibase to do things the Spring way to be consistent and avoid developer confusion, what am I missing?

Thanks for any help!

0

There are 0 answers