ChatGPT解决这个技术问题 Extra ChatGPT

Spring Boot + JPA : Column name annotation ignored

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 
This question is about explicitly provided column name being altered rather than ignored. It boils down to this being executed instead of expected transparent variant. Hibernate may actually ignore @Column(name="...") annotation, for example when you use other than expected access type, but that's not the case here.

Y
Yann39

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

spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl ,only this property is required for keep the name as it is .
I had the same issue and adding those 2 properties solved it for me. I'm running Spring Boot 1.4.3
This is the only solution that worked for me too. I'm using Spring Boot 1.4.2
I am using Spring Boot 1.5.9.RELEASE, this post works for me
Awesome.. I was wondering why it was ignoring my @Column annotation. Finally this helped me. To me, I feel like this is either a bug or missing functionality.
P
Phil Webb

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")

Hi, Phil. By using spring boot, I have add spring.jpa.hibernate.naming.strategy: org.hibernate.cfg.EJB3NamingStrategy. But It looks like not work for me. can you help me?
The important part of the response is to put the name in lower case! I advise not to change the stategy but to put the name is lower case as column name are case insensitive!
I have mixed case column names in MS SQL Server, for example ColumnName. MS SQL Server is case insensitive so this would work at runtime but JPA Tools complains that columname is not found. @teteArg's answer solves this problem, although I only needed PhysicalNamingStrategyStandardImpl.
n
ncaralicea

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.


I had the same problem. I added an issue report here: github.com/spring-projects/spring-boot/issues/2129
It’s actually not ignored, just the default spring naming strategy is applied on the given name attribute. Read @PhilWebb answer
O
Orhan

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 :))


1. Actually that's not true, column names can be case sensitive depending on configuration of the database you are using... 2. @Column name - as name suggests should be a place to provide database column name, not some identifier which a framework will change during runtime..
1. Thanks, can you give an example of db where column names are case sensitive by default? 2. Actually @Column gives us logical names that are resolved to physical names by PhysicalNamingStrategy, at least that seems to be what the doc says: docs.jboss.org/hibernate/orm/5.1/userguide/html_single/chapters/…
1.Sorry I can't as I don't care which one has it by default, I care what settings are set by DBA on the one I'm using. 2. That's unfortunately true - it's just my personal opinion that this approach is wrong as it forces me to think or about how name would be mapped to column at the end, or which naming strategy to use which doesn't touch provided names.
True, that would be most intuitive solution, and of course better documentation on this would not hurt.
an explicitly set column name should under all conditions override an implicitly generated one. If it doesn't, that's a bug in the JPA implementation.
S
Sanjiv Jivan

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)

C
Community

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.


d
double-beep

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;

Z
Zakib Ali

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;

L
Lerk

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


d
dawidR

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


Are you sure you have quotes in the db table name directly?
Only that that worked for me also. I tought JPA was suppose to help, not give us free trouble. @Kamil, mine doesnt have quotes and this is the only one that worked. Maybe this a PostgreSQL particular problem, idk.
actually backslashes in column name is not necessary anymore (2.6.5)
j
java-addict301

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.


P
Piaget Hadzizi

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


u
user3121260

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 :)


I don't think its a maven versioning issue