Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring boot JPA insert in TABLE with uppercase name with Hibernate

People also ask

Is JPA table name case sensitive?

When working with JPA, one problem that you might encounter is that the table name in the database is defined in lowercase, but the entity that we declare to define the table name is uppercase or vice versa. Some database systems do not have any problem with that kind of declaration, but some databases do not.

What is Spring JPA Hibernate naming physical strategy?

Hibernate uses the Physical Naming Strategy to map our logical names to a SQL table and its columns. By default, the physical name will be the same as the logical name that we specified in the previous section. If we want to customize the physical names, we can create a custom PhysicalNamingStrategy class.

What does findById return in JPA?

Its findById method retrieves an entity by its id. The return value is Optional<T> . Optional<T> is a container object which may or may not contain a non-null value. If a value is present, isPresent returns true and get returns the value.

What is @column annotation in spring boot?

@Column annotation is used for Adding the column the name in the table of a particular MySQL database. Syntax: @Column(name=”DESC”, nullable=false, length=512) public String getDescription() {


On hibernate 5, it would be

spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

in your application.properties file.


As @jasonleakey suggested we can consider using naming-strategy as below.

spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

this tells Hibernate to generate SQL's as exactly as specified in the @Table (name=" ") or @Column(name=" "). All well.

But keep in mind - while using PhysicalNamingStrategy without @Table, @Column annotations in the entity class, hibernate generates SQL using class name and variable names. Consider the below java class

Class Employee {
   private String firstName;
   private String lastName; 
}

then the generated sql would be,

select employee0_.firstName,employee0_lastName from Employee employee0_;

Unfortunately this is not a great choice as typically we would have defined the columns in DB as FIRST_NAME and LAST_NAME and table name as EMPLOYEE. Had you not used PhysicalNamingStrategy the SQL would have been

select employee0_.first_name,employee0_last_name from employee employee0_;

so it's really a choice between the below two options.

  • Use PhysicalStrategy and explicitly define all tables names/column names in java code with @Table and @Column annotations.
    or
  • Define lowercase table name in db and let hibernate automatically generate table names/column names for us.

The solution is to add:

spring.jpa.hibernate.naming_strategy=org.hibernate.cfg.EJB3NamingStrategy

to application.properties


You'll need to escape the table name with tics(`) to make it case sensitive.

@Table(name = "`ITEMS_TO_REGISTER`")

You can implement your own strategy and invoke it from application.properties:

spring.jpa.hibernate.naming.physical-strategy=com.proto.CustomPhysicalNamingStrategy

Bellow an example that always capitalize the first letter

import java.io.Serializable;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.model.naming.PhysicalNamingStrategy;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;

public class CustomPhysicalNamingStrategy implements PhysicalNamingStrategy, Serializable {
    /**
     * Singleton access
     */
    public static final CustomPhysicalNamingStrategy INSTANCE = new CustomPhysicalNamingStrategy();

    @Override
    public Identifier toPhysicalCatalogName(Identifier name, JdbcEnvironment context) {
        return capitalize(name);
    }

    @Override
    public Identifier toPhysicalSchemaName(Identifier name, JdbcEnvironment context) {
        return capitalize(name);
    }

    @Override
    public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment context) {
        return capitalize(name);
    }

    @Override
    public Identifier toPhysicalSequenceName(Identifier name, JdbcEnvironment context) {
        return capitalize(name);
    }

    @Override
    public Identifier toPhysicalColumnName(Identifier name, JdbcEnvironment context) {
        return capitalize(name);
    }

    private Identifier capitalize(Identifier name) {
        if (name == null)
            return null;
        if (name.isQuoted())
            return name;
        String text = StringUtils.capitalize(name.getText());
        return Identifier.toIdentifier(text);
    }
}

You can try:

@Entity
@Table(name = "ITEMS_TO_REGISTER")
public class ItemsToRegister implements Serializable {
   ...