1. Introduction

Spring Data JPA offers many features to use JPA in an application. Among those features, there’s the standardization of table and column names in both DDL and DML queries.

In this short tutorial, we’re going to see how to configure this default naming convention.

2. Default Naming Convention

First of all, let’s see what Spring’s default naming convention regarding table and column names.

Let’s imagine we have a Person entity:

@Entity
public class Person {
    @Id
    private Long id;
    private String firstName;
    private String lastName;
}

We have a few names here that have to be mapped to the database. Well, Spring uses lower snake case by default, which means it uses only lower case letters and separates words with underscores. Therefore, the table creation query for the Person entity would be:

create table person (id bigint not null, first_name varchar(255), last_name varchar(255), primary key (id));

And a selection query returning all first names would be:

select first_name from person;

To do that, *Spring implemented its version of the Hibernate’s PhysicalNamingStrategy: SpringPhysicalNamingStrategy.*

3. RDMS Case-Sensitivity

Before going into the details of how to create our custom naming convention, let’s talk a bit about how the RDMS is managing the case of the identifiers.

There are two scenarios to consider: the RDMS is case-sensitive, or it is not.

In the first situation, the RDMS will strictly match identifiers that have the same case. Therefore, in our example, the following query would work:

select first_name from person;

While this one will throw an error and not even return a result:

select FIRST_NAME from PERSON;

On the other hand, for an RDMS that is case-insensitive, both queries would have worked.

What would we do to force the RDMS to match identifiers regarding their case as well? We can use quoted identifiers (for example, “person”).

By using quotes around our identifiers, we tell the database it should also match the case when comparing those identifiers with table and column names. So, still using our example, the following query would work:

select "first_name" from "person";

While this one wouldn’t:

select "first_name" from "PERSON";

That’s in theory though, because each RDMS manages quoted identifiers in its own way, so mileage varies.

4. Custom Naming Convention

Now, let’s implement our own naming convention.

Imagine we can’t use the Spring lower snake case strategy, but we need to use upper snake case. Then, we’d need to provide an implementation of PhysicalNamingStrategy.

As we’re going to keep to snake case, the fastest option is to inherit from the SpringPhysicalNamingStrategy and turn identifiers to upper case:

public class UpperCaseNamingStrategy extends SpringPhysicalNamingStrategy {
    @Override
    protected Identifier getIdentifier(String name, boolean quoted, JdbcEnvironment jdbcEnvironment) {
        return new Identifier(name.toUpperCase(), quoted);
    }
}

We’re just overriding the getIdentifier() method, which is in charge of turning the identifiers to lower case in the super-class. Here we’re using it to convert them to upper case.

Once we’ve written our implementation, we must register it so that Hibernate knows to use it. Using Spring, this is done by setting the spring.jpa.hibernate.naming.physical-strategy property in our application.properties:

spring.jpa.hibernate.naming.physical-strategy=com.baeldung.namingstrategy.UpperCaseNamingStrategy

Now, our queries are using upper case identifiers:

create table PERSON (ID bigint not null, FIRST_NAME varchar(255), LAST_NAME varchar(255), primary key (ID));

select FIRST_NAME from PERSON;

Let’s say that we want to use quoted identifiers so that the RDMS is forced to match the case. Then we would have to use true as the quoted argument of the Identifier() constructor**:

@Override
protected Identifier getIdentifier(String name, boolean quoted, JdbcEnvironment jdbcEnvironment) {
    return new Identifier(name.toUpperCase(), true);
}

After what our queries would present quoted identifiers:

create table "PERSON" ("ID" bigint not null, "FIRST_NAME" varchar(255), "LAST_NAME" varchar(255), primary key ("ID"));

select "FIRST_NAME" from "PERSON";

5. Conclusion

In this short article, we talked about the possibilities of implementing a custom naming strategy using Spring Data JPA and how the RDMS will handle our DDL and DML statements regarding its internal configuration.

As usual, the full code for this article can be found over on GitHub.