Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Boot Hibernate 5 Ignoring @Table and @Column

This is driving me mad.

I'm implementing Spring Social and it requires you to have a database table named UserConnection (instead of using the standard naming convention of using an underscore to separate the two words).

So in my naive world view, I assumed it would be easily solved by specifying @Table(name="UserConnection")... but no, that would be all too easy.

The annotation is ignored and the table is created as user_connection which then causes Spring Social to have a hissy fit.

Please tell me there's some easy way to tell my Spring Boot app to just name that one table (and its corresponding columns) to use a camel-case naming convention instead of the standard one.

like image 598
Trevor Avatar asked Jan 28 '17 16:01

Trevor


People also ask

Is @column annotation necessary?

@Column. Let's start with the @Column annotation. It is an optional annotation that enables you to customize the mapping between the entity attribute and the database column.

What is @column annotation in spring boot?

Spring Boot is a microservice-based framework and making a production-ready application in it takes very little time. In this article, we will discuss how to change the column name in the Spring project using JPA. @Column annotation is used for Adding the column the name in the table of a particular MySQL database.

What is @table annotation in spring boot?

The @Table annotation allows you to specify the details of the table that will be used to persist the entity in the database. The @Table annotation provides four attributes, allowing you to override the name of the table, its catalog, and its schema, and enforce unique constraints on columns in the table.

What is columnDefinition in hibernate?

columnDefinition definition: The SQL fragment that is used when generating the DDL for the column.


1 Answers

TL; DR

Add the following to your application.yml file:

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

Or your application.properties:

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

Detailed Answer

As Spring Boot 1.4 release notes states:

SpringNamingStrategy is no longer used as Hibernate 5.1 has removed support for the old NamingStrategy interface. A new SpringPhysicalNamingStrategy is now auto-configured which is used in combination with Hibernate’s default ImplicitNamingStrategy. This should be very close to (if not identical) to Spring Boot 1.3 defaults, however, you should check your Database schema is correct when upgrading.

This new PhysicalNamingStrategy follows Spring recommended naming conventions. Anyway if you want total control over physical naming, you're better off using the org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl. You can switch to that naming strategy by adding the following to your application.yml:

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

The annotation is ignored and the table is created as user_connection which then causes Spring Social to have a hissy fit.

The apply method of SpringPhysicalNamingStrategy is the key to understand this behavior:

private Identifier apply(Identifier name, JdbcEnvironment jdbcEnvironment) {
    if (name == null) {
        return null;
    }
    StringBuilder builder = new StringBuilder(name.getText().replace('.', '_'));
    for (int i = 1; i < builder.length() - 1; i++) {
        if (isUnderscoreRequired(builder.charAt(i - 1), builder.charAt(i),
                builder.charAt(i + 1))) {
            builder.insert(i++, '_');
        }
    }
    return getIdentifier(builder.toString(), name.isQuoted(), jdbcEnvironment);
}

private boolean isUnderscoreRequired(char before, char current, char after) {
    return Character.isLowerCase(before) && Character.isUpperCase(current)
            && Character.isLowerCase(after);
}

It basically replaces any . and case changes (take a look at isUnderscoreRequired method) with an underscore.

like image 51
Ali Dehghani Avatar answered Sep 16 '22 21:09

Ali Dehghani