Spring Boot + JPA : Column name annotation ignored

JavaHibernateJpaSpring Boot

Java Problem Overview


I have a Spring Boot application with dependency spring-boot-starter-data-jpa. My entity class has a column annotation with a column name. For example:

@Column(name="TestName")
private String testName;

SQL generated by this created test_name as the columns name. After looking for a solution I have found that spring.jpa.hibernate.naming_strategy=org.hibernate.cfg.EJB3NamingStrategy solved the problem (column name is taken from column annotation).

Still, my question is why without naming_strategy set to EJB3NamingStrategy JPA is ignoring column annotation? Maybe hibernate dialect has something to do with it? I'm connecting to MS SQL 2014 Express and my logs contain:

Unknown Microsoft SQL Server major version [12] using SQL Server 2000 dialect
Using dialect: org.hibernate.dialect.SQLServerDialect 

Java Solutions


Solution 1 - Java

For Hibernate 5, I solved this issue by adding the following lines in my application.properties file:

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

Solution 2 - Java

By default Spring uses org.springframework.boot.orm.jpa.SpringNamingStrategy to generate table names. This is a very thin extension of org.hibernate.cfg.ImprovedNamingStrategy. The tableName method in that class is passed a source String value but it is unaware if it comes from a @Column.name attribute or if it has been implicitly generated from the field name.

The ImprovedNamingStrategy will convert CamelCase to SNAKE_CASE where as the EJB3NamingStrategy just uses the table name unchanged.

If you don't want to change the naming strategy you could always just specify your column name in lowercase:

@Column(name="testname")

Solution 3 - Java

It seems that

> @Column(name="..")

is completely ignored unless there is

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

specified, so to me this is a bug.

I spent a few hours trying to figure out why @Column(name="..") was ignored.

Solution 4 - Java

The default strategy for @Column(name="TestName") will be test_name, this is correct behavior!

If you have a column named TestName in your database you should change Column annotation to @Column(name="testname").

This works because database does not care if you name your column TestName or testname (column names are case insensitive!!).

But beware, the same does not apply for database name and table names, that are case sensitive on Unix systems but case in sensitive on Windows systems (the fact that probably kept a lot of people awake at night, working on windows but deploying on linux :))

Solution 5 - Java

The only solution that worked for me was the one posted by teteArg above. I'm on Spring Boot 1.4.2 w/Hibernate 5. Namely

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

For additional insight I'm posting the call trace so that its clear what calls Spring is making into Hibernate to setup the naming strategy.

	  at org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl.toPhysicalColumnName(PhysicalNamingStrategyStandardImpl.java:46)
  at org.hibernate.cfg.Ejb3Column.redefineColumnName(Ejb3Column.java:309)
  at org.hibernate.cfg.Ejb3Column.initMappingColumn(Ejb3Column.java:234)
  at org.hibernate.cfg.Ejb3Column.bind(Ejb3Column.java:206)
  at org.hibernate.cfg.Ejb3DiscriminatorColumn.buildDiscriminatorColumn(Ejb3DiscriminatorColumn.java:82)
  at org.hibernate.cfg.AnnotationBinder.processSingleTableDiscriminatorProperties(AnnotationBinder.java:797)
  at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:561)
  at org.hibernate.boot.model.source.internal.annotations.AnnotationMetadataSourceProcessorImpl.processEntityHierarchies(AnnotationMetadataSourceProcessorImpl.java:245)
  at org.hibernate.boot.model.process.spi.MetadataBuildingProcess$1.processEntityHierarchies(MetadataBuildingProcess.java:222)
  at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:265)
  at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:847)
  at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:874)
  at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60)
  at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:353)
  at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:373)
  at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:362)
  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1642)
  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1579)
  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
  at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
  at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
  - locked <0x1687> (a java.util.concurrent.ConcurrentHashMap)
  at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
  at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
  at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1081)
  at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:856)
  at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542)
  - locked <0x1688> (a java.lang.Object)
  at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:761)
  at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:371)
  at org.springframework.boot.SpringApplication.run(SpringApplication.java:315)
  at org.springframework.boot.SpringApplication.run(SpringApplication.java:1186)
  at org.springframework.boot.SpringApplication.run(SpringApplication.java:1175)

Solution 6 - Java

teteArg, thank you so much. Just an added information so, everyone bumping into this question will be able to understand why.

What teteArg said is indicated on the Spring Boot Common Properties: http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html

Apparently, spring.jpa.hibernate.naming.strategy is not a supported property for Spring JPA implementation using Hibernate 5.

Solution 7 - Java

Turns out that I just have to convert @column name testName to all small letters, since it was initially in camel case.

Although I was not able to use the official answer, the question was able to help me solve my problem by letting me know what to investigate.

Change:

@Column(name="testName")
private String testName;

To:

@Column(name="testname")
private String testName;

Solution 8 - Java

you have to follow some naming strategy when you work with spring jpa. The column name should be in lowercase or uppercase.

@Column(name="TESTNAME")
private String testName;

or

@Column(name="testname")
private String testName;

keep in mind that, if you have your column name "test_name" format in the database then you have to follow the following way

@Column(name="TestName")
private String testName;

or

@Column(name="TEST_NAME")
private String testName;

or

@Column(name="test_name")
private String testName;

Solution 9 - Java

If you want to use @Column(...), then use small-case letters always even though your actual DB column is in camel-case.

Example: If your actual DB column name is TestName then use:

  @Column(name="testname") //all small-case

If you don't like that, then simply change the actual DB column name into: test_name

Solution 10 - Java

I also tried all the above and nothing works. I got field called "gunName" in DB and i couldn't handle this, till i used example below:

@Column(name="\"gunName\"")
public String gunName;

with properties:

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

also see this: https://stackoverflow.com/a/35708531

Solution 11 - Java

In my case, the annotation was on the getter() method instead of the field itself (ported from a legacy application).

Spring ignores the annotation in this case as well but doesn't complain. The solution was to move it to the field instead of the getter.

Solution 12 - Java

I tried all the above and it didn't work. This worked for me:

@Column(name="TestName")
public String getTestName(){//.........

Annotate the getter instead of the variable

Solution 13 - Java

Using maven 3.8.3, I found funny case where the column name of the table is following the get/set method naming. Even when I added a new field in the entity, it didn't create a new column in the table if I didn't specify the get/set method.

But, if I remove all get/set methods from the entity class, the naming of columns in the table follows the naming of fields in the entity class.

(I'm a rookie, it might be a feature which ensures logical correctness :)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKamilView Question on Stackoverflow
Solution 1 - JavateteArgView Answer on Stackoverflow
Solution 2 - JavaPhil WebbView Answer on Stackoverflow
Solution 3 - JavancaraliceaView Answer on Stackoverflow
Solution 4 - JavaOrhanView Answer on Stackoverflow
Solution 5 - JavaSanjiv JivanView Answer on Stackoverflow
Solution 6 - JavaRomeo Jr MarananView Answer on Stackoverflow
Solution 7 - JavaMohammad CaliView Answer on Stackoverflow
Solution 8 - JavaZakib AliView Answer on Stackoverflow
Solution 9 - JavaDeanView Answer on Stackoverflow
Solution 10 - JavadawidRView Answer on Stackoverflow
Solution 11 - Javajava-addict301View Answer on Stackoverflow
Solution 12 - JavaPiaget HadziziView Answer on Stackoverflow
Solution 13 - Javauser3121260View Answer on Stackoverflow