Hibernate Physical Naming Strategy

Imagine having a tool that can automatically detect JPA and Hibernate performance issues. Wouldn’t that be just awesome?

Well, Hypersistence Optimizer is that tool! And it works with Spring Boot, Spring Framework, Jakarta EE, Java EE, Quarkus, or Play Framework.

So, enjoy spending your time on the things you love rather than fixing performance issues in your production system on a Saturday night!

Introduction

In this article, I’m going to show you how the Hibernate Physical Naming Strategy works and how you can use it to customize the default mapping between entity attributes and database identifiers.

Hibernate PhysicalNamingStrategy

Since version 5, Hibernate offers the PhysicalNamingStrategy interface to customize the mapping between entity attributes and database identifiers.

The Hibernate PhysicalNamingStrategy interface looks as follows:

Hibernate PhysicalNamingStrategy

The Hibernate PhysicalNamingStrategy methods allow you to customize the default naming conventions for the following database identifiers:

  • toPhysicalCatalogName – customize the default database catalog naming convention
  • toPhysicalSchemaName – customize the default database schema naming convention
  • toPhysicalTableName – customize the default database table naming convention
  • toPhysicalSequenceName – customize the default database sequence naming convention
  • toPhysicalColumnName – customize the default database table column naming convention

The default implementation of the PhysicalNamingStrategy interface is the PhysicalNamingStrategyStandardImpl class.

Customizing the Hibernate Physical Naming Strategy

If you want to provide a default camelCase to snake_case mapping between the Java entity attributes and the database identifiers, you can create the following CamelCaseToSnakeCaseNamingStrategy that extends the default PhysicalNamingStrategyStandardImpl class and defines the new default mapping rules:

public class CamelCaseToSnakeCaseNamingStrategy extends PhysicalNamingStrategyStandardImpl {

    public static final String CAMEL_CASE_REGEX = "([a-z]+)([A-Z]+)";
    public static final String SNAKE_CASE_PATTERN = "$1\\_$2";

    @Override
    public Identifier toPhysicalCatalogName(
            Identifier name, JdbcEnvironment context) {
        return formatIdentifier(
            super.toPhysicalCatalogName(name, context)
        );
    }

    @Override
    public Identifier toPhysicalSchemaName(
            Identifier name, JdbcEnvironment context) {
        return formatIdentifier(
            super.toPhysicalSchemaName(name, context)
        );
    }

    @Override
    public Identifier toPhysicalTableName(
            Identifier name, JdbcEnvironment context) {
        return formatIdentifier(
            super.toPhysicalTableName(name, context)
        );
    }

    @Override
    public Identifier toPhysicalSequenceName(
            Identifier name, JdbcEnvironment context) {
        return formatIdentifier(
            super.toPhysicalSequenceName(name, context)
        );
    }

    @Override
    public Identifier toPhysicalColumnName(
            Identifier name, JdbcEnvironment context) {
        return formatIdentifier(
            super.toPhysicalColumnName(name, context)
        );
    }

    private Identifier formatIdentifier(
            Identifier identifier) {
        if (identifier != null) {
            String name = identifier.getText();

            String formattedName = name.replaceAll(
                CAMEL_CASE_REGEX, 
                SNAKE_CASE_PATTERN
            ).toLowerCase();

            return !formattedName.equals(name) ?
                    Identifier.toIdentifier(
                        formattedName, 
                        identifier.isQuoted()
                    ) :
                    identifier;
        } else {
            return null;
        }
    }
}

If you want to use a camelCase to snake_case naming strategy, you don’t need to create the CamelCaseToSnakeCaseNamingStrategy as you can get it via the Hypersistence Utils.

Registering the custom Hibernate Physical Naming Strategy

If you’re using Spring Boot, then you can register the customer Hibernate PhysicalNamingStrategy via the hibernate.physical_naming_strategy Hibernate configuration property:

spring.jpa.properties.hibernate.physical_naming_strategy=io.hypersistence.utils.hibernate.naming.CamelCaseToSnakeCaseNamingStrategy

Or, if you’re using Java EE or Jakarta EE, then you can provide the Hibernate Physical Naming Strategy via the persistence.xml property file:

<property 
    name="hibernate.physical_naming_strategy"
    value="io.hypersistence.utils.hibernate.naming.CamelCaseToSnakeCaseNamingStrategy"
/>

I'm running an online workshop on the 20-21 and 23-24 of November about High-Performance Java Persistence.

If you enjoyed this article, I bet you are going to love my Book and Video Courses as well.

Conclusion

The Hibernate PhysicalNamingStrategy interface and the hibernate.physical_naming_strategy configuration property allow you to customize the mapping between Java Object and database identifiers.

Therefore, the Hibernate Physical Naming Strategy is useful to define default mappings strategies, as a Java cameCase to database snake_case mapping. For more details about the Hypersistence Utils CamelCaseToSnakeCaseNamingStrategy class, check out this article as well.

Transactions and Concurrency Control eBook

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.