Java Spring Boot + JPA:列名注释被忽略

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25283198/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 00:02:34  来源:igfitidea点击:

Spring Boot + JPA : Column name annotation ignored

javahibernatejpaspring-boot

提问by Kamil

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:

我有一个具有依赖项的 Spring Boot 应用程序spring-boot-starter-data-jpa。我的实体类有一个带有列名的列注释。例如:

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

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

由此生成的 SQLtest_name作为列名创建。在寻找解决方案后,我发现spring.jpa.hibernate.naming_strategy=org.hibernate.cfg.EJB3NamingStrategy解决了问题(列名取自列注释)。

Still, my question is why without naming_strategy set to EJB3NamingStrategyJPA 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:

不过,我的问题是为什么没有将naming_strategy 设置为EJB3NamingStrategyJPA 会忽略列注释?也许休眠方言与它有关?我正在连接到 MS SQL 2014 Express 并且我的日志包含:

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

采纳答案by teteArg

For hibernate5 I solved this issue by puting next lines in my application.properties file:

对于 hibernate5,我通过在 application.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

回答by Phil Webb

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

默认情况下,Spring 使用org.springframework.boot.orm.jpa.SpringNamingStrategy生成表名。这是org.hibernate.cfg.ImprovedNamingStrategy. tableName该类中的方法传递了一个源String值,但它不知道它是来自@Column.name属性还是从字段名称隐式生成。

The ImprovedNamingStrategywill convert CamelCaseto SNAKE_CASEwhere as the EJB3NamingStrategyjust uses the table name unchanged.

ImprovedNamingStrategy会转换CamelCaseSNAKE_CASE其中的EJB3NamingStrategy只是使用表名不变。

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

如果您不想更改命名策略,您可以始终以小写形式指定列名:

@Column(name="testname")

回答by ncaralicea

It seems that

看起来

@Column(name="..")

@Column(name="..")

is completely ignored unless there is

完全忽略,除非有

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

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.

我花了几个小时试图弄清楚为什么 @Column(name="..") 被忽略了。

回答by Romeo Jr Maranan

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

teteArg,非常感谢。只是一个附加的信息,所以每个碰到这个问题的人都能理解为什么。

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

什么teteArg说,在春季启动通用属性表示:http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html

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

显然,spring.jpa.hibernate.naming.strategy不是使用 Hibernate 5 的 Spring JPA 实现支持的属性。

回答by 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

唯一对我有用的解决方案是上面 teteArg 发布的解决方案。我使用的是带有 Hibernate 5 的 Spring Boot 1.4.2。即

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.

为了获得更多见解,我发布了调用跟踪,以便清楚 Spring 调用 Hibernate 以设置命名策略的内容。

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

回答by Orhan

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

@Column(name="TestName")will的默认策略是test_name,这是正确的行为!

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

如果您TestName的数据库中有一个名为的列,则应将 Column 注释更改为@Column(name="testname").

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

这是有效的,因为数据库不关心您是将列命名为TestName 还是 testname (列名不区分大小写!!)。

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

但请注意,这同样不适用于数据库名称和表名称,它们在 Unix 系统上区分大小写,但在 Windows 系统上区分大小写(这一事实可能让很多人彻夜难眠,在 Windows 上工作但在 linux 上部署:))

回答by Dean

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

如果你想使用@Column(...),那么即使你的实际数据库列是驼峰式的,也总是使用小写字母。

Example: If your actual DB column name is TestNamethen use:

示例:如果您的实际数据库列名称是TestName然后使用:

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

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

如果您不喜欢那样,那么只需将实际的数据库列名称更改为:test_name

回答by java-addict301

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

就我而言,注释位于 getter() 方法上,而不是字段本身(从遗留应用程序移植而来)。

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.

在这种情况下,Spring 也会忽略注释,但不会抱怨。解决方案是将其移动到现场而不是吸气剂。

回答by Mohammad Cali

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

原来我只需要将@column名称 testName转换为所有小写字母,因为它最初是驼峰式的。

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;