2

I'm using Spring Boot 2.3.4 / Spring Data / Hibernate / MySQL 8.

My db table is called "productDef". I have an entity object "ProductDef".

When I do a "list all" query I get this error ...

java.sql.SQLSyntaxErrorException: Table 'mydatabase.product_def' doesn't exist

Why is Hibernate looking for table "product_def"?

I tried adding annotation @Table(name="productDef") to the entity, but that didn't help.

If I rename the db table to "product_def", my code works. But unfortunately I cannot rename the db table names for my project.

What am I missing?

UPDATE:

Solution was to implement a custom PhysicalNamingStrategy to prevent the "productDef" becoming "product_def".

However, while this worked for the @Table name annotation, it did not work for the @Column name annotation.

According to this discussion thread, the ignoring of @Column name annotation is a bug.

Adding this to application.properties:

spring.jpa.properties.hibernate.physical_naming_strategy=com.myapp.dao.RealNamingStrategyImpl

And implementing the class like this:

package com.myapp.dao;

import java.io.Serializable;

import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.model.naming.PhysicalNamingStrategy;
import org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;

public class RealNamingStrategyImpl extends org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy implements Serializable {

    public static final PhysicalNamingStrategy INSTANCE = new PhysicalNamingStrategyStandardImpl();

    @Override
    public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment context) {
        return new Identifier(name.getText(), name.isQuoted());
    }

    @Override
    public Identifier toPhysicalColumnName(Identifier name, JdbcEnvironment context) {
        return new Identifier(name.getText(), name.isQuoted());
    }

}
AvaTaylor
  • 623
  • 4
  • 16

1 Answers1

4

This is the default Naming Strategy used by Hibernate and defined by JPA 2.0, specifically, the physicalNamingStrategy: it converts camel case to underscores for table and column names.

See: https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/chapters/domain/naming.html#PhysicalNamingStrategy

While the purpose of an ImplicitNamingStrategy is to determine that an attribute named accountNumber maps to a logical column name of accountNumber when not explicitly specified, the purpose of a PhysicalNamingStrategy would be, for example, to say that the physical column name should instead be abbreviated acct_num.

There are multiple ways to specify the PhysicalNamingStrategy to use. First, applications can specify the implementation using the hibernate.physical_naming_strategy configuration setting.

With Spring, you can also configure this strategy with the property: spring.jpa.hibernate.naming.physical-strategy

By default, Spring Boot configures the physical naming strategy with SpringPhysicalNamingStrategy. This implementation provides the same table structure as Hibernate 4: all dots are replaced by underscores and camel casing is replaced by underscores as well. By default, all table names are generated in lower case, but it is possible to override that flag if your schema requires it.

Guillaume F.
  • 5,905
  • 2
  • 31
  • 59
  • Thanks! Follow up question ... any idea why `@Table(name="productDef")` is not forcing Hibernate to use the table name `productDef` ? – AvaTaylor Oct 08 '20 at 20:26
  • I edited my answer about SpringBoot's specificity. You have to override the strategy with a custom one if you don't want this naming convention enforced. – Guillaume F. Oct 08 '20 at 20:33
  • Thanks again for the help ... but isn't `@Table(name = "productDef")` supposed to force Hibernate to use that table name? – AvaTaylor Oct 08 '20 at 20:37
  • There are two strategy types, the "implicit" and the "physical". Your annotation bypasses the "implicit" strategy. But everything still goes through the "physical" strategy, with or without an annotation. This is the strategy you want to override. – Guillaume F. Oct 08 '20 at 20:39
  • 1
    Thanks for the help. I got it working for the table name by implementing a custom SpringPhysicalNamingStrategy ... but now I'm having the same problem with column name ... and after some digging it appears there's a bug that's causing the @Column annotation to be ignored. Discussion thread here: https://github.com/spring-projects/spring-boot/issues/2129 – AvaTaylor Oct 08 '20 at 22:58
  • 1
    Hi -- just FYI I posted a followup question about my "ignored @Column" annotation here. Please take a look! https://stackoverflow.com/questions/64271945/how-do-i-get-columnname-productname-to-not-be-ignored-by-spring-boot-jp – AvaTaylor Oct 08 '20 at 23:28