繁体   English   中英

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

[英]Spring Boot + JPA : Column name annotation ignored

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

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

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

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

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

对于 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

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

ImprovedNamingStrategy SNAKE_CASE会将CamelCase转换为SNAKE_CASE ,而EJB3NamingStrategy只是使用未更改的表名。

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

@Column(name="testname")

看起来

@Column(name="..")

完全忽略,除非有

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

指定,所以对我来说这是一个错误。

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

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

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

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

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

唯一对我有用的解决方案是上面 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

为了获得更多见解,我发布了调用跟踪,以便清楚 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$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)

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

teteArg所说的内容在 Spring Boot Common Properties 中指出: http : //docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html

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

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

虽然我无法使用官方答案,但该问题通过让我知道要调查的内容来帮助我解决问题。

改变:

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

到:

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

使用 spring jpa 时必须遵循一些命名策略。 列名应为小写或大写。

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

或者

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

请记住,如果您在数据库中有列名“test_name”格式,那么您必须遵循以下方式

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

或者

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

或者

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

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

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

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

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

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

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

我尝试了以上所有方法,但没有奏效。 这对我有用:

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

注释 getter 而不是变量

我也尝试了以上所有方法,但没有任何效果。 我在数据库中有一个名为“gunName”的字段,但我无法处理这个问题,直到我使用下面的示例:

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

有属性:

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

另请参阅: https : //stackoverflow.com/a/35708531

使用 maven 3.8.3,我发现了一个有趣的案例,其中表的列名遵循 get/set 方法命名。 即使我在实体中添加了一个新字段,如果我没有指定 get/set 方法,它也不会在表中创建新列。

但是,如果我从实体类中删除所有 get/set 方法,则表中列的命名遵循实体类中字段的命名。

(我是菜鸟,这可能是确保逻辑正确性的功能:)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM