Spring Boot + JPA : 열 이름 주석 무시


121

종속성이있는 Spring Boot 애플리케이션이 spring-boot-starter-data-jpa있습니다. 내 항목 클래스에는 열 이름이있는 열 주석이 있습니다. 예를 들면 :

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

이에 의해 생성 된 SQL test_name은 열 이름으로 생성됩니다 . 해결책을 찾은 spring.jpa.hibernate.naming_strategy=org.hibernate.cfg.EJB3NamingStrategy후 문제 가 해결 되었음을 발견했습니다 (열 이름은 열 주석에서 가져옴).

그래도 내 질문은 왜 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 

1
이 질문은 명시 적으로 제공된 열 이름이 무시 되지 않고 변경 되는 것에 관한 것 입니다. 그것은 아래로 비등 대신 예상으로 실행되는 투명 변형 . 예를 들어 예상되는 액세스 유형이 아닌 다른 유형을 사용할 때 Hibernate는 실제로 주석을 무시할 수 있지만 여기에서는 그렇지 않습니다. @Column(name="...")
Vlastimil Ovčáčík

답변:


163

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

30
spring.jpa.hibernate.naming.physical-strategy = org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl, 이름을 그대로 유지하려면이 속성 만 필요합니다.
abhishek ringsia

1
나는 같은 문제가 있었고 그 두 가지 속성을 추가하여 나를 위해 해결했습니다. 저는 Spring Boot 1.4.3을 실행하고 있습니다
Johan

1
이것은 나에게도 효과가 있었던 유일한 솔루션입니다. 저는 Spring Boot 1.4.2
Sanjiv Jivan을

저는 Spring Boot 1.5.9.RELEASE를 사용하고 있습니다.이 게시물은 저에게 효과적입니다
IcyBrk

멋져요 .. 왜 내 @Column 주석을 무시하는지 궁금합니다. 마침내 이것은 나를 도왔습니다. 제게는 이것이 버그이거나 기능이없는 것 같습니다.
Raju Penumatsa

86

기본적으로 Spring은 org.springframework.boot.orm.jpa.SpringNamingStrategy테이블 이름을 생성하는 데 사용 합니다. 이것은의 매우 얇은 확장입니다 org.hibernate.cfg.ImprovedNamingStrategy. tableName해당 클래스 의 메서드에는 소스 String값 이 전달 되지만 @Column.name속성 에서 가져온 것인지 필드 이름에서 암시 적으로 생성되었는지 는 인식하지 못합니다 .

는 변경되지 않은 테이블 이름을 사용하는 곳으로 ImprovedNamingStrategy변환 CamelCase됩니다 .SNAKE_CASEEJB3NamingStrategy

이름 지정 전략을 변경하지 않으려면 항상 열 이름을 소문자로 지정할 수 있습니다.

@Column(name="testname")

1
안녕, 필. 스프링 부트를 사용하여 spring.jpa.hibernate.naming.strategy : org.hibernate.cfg.EJB3NamingStrategy를 추가했습니다. 그러나 그것은 나를 위해 작동하지 않는 것 같습니다. 도와주세요?
BeeNoisy

응답의 중요한 부분은 이름을 소문자로 입력하는 것입니다! 상태를 변경하지 말고 열 이름이 대소 문자를 구분하지 않으므로 이름을 소문자로 입력하는 것이 좋습니다!
loicmathieu

31

그것은 보인다

@ 열 (name = "..")

없는 한 완전히 무시됩니다

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

나에게 이것은 버그입니다.

@Column (name = "..")이 무시 된 이유를 알아 내려고 몇 시간을 보냈습니다.


4
나는 같은 문제가 있었다. 여기에 문제 보고서를 추가 : github.com/spring-projects/spring-boot/issues/2129
Kacper86

감사합니다. 내 앱을 기존 db로 가리 키기 위해 하루를 잃었습니다.
Dmitry Erokhin 2015

실제로 무시되지 않고 기본 스프링 이름 지정 전략이 주어진 이름 속성에 적용됩니다. 읽기 @PhilWebb 답변
미셸 Feldheim

16

의 기본 전략은 @Column(name="TestName")입니다 test_name. 이것은 올바른 동작입니다!

TestName데이터베이스에 이름이 지정된 열이있는 경우 열 주석을로 변경해야합니다 @Column(name="testname").

이것은 데이터베이스가 열 이름을 TestName 또는 testname ( 열 이름은 대소 문자를 구분하지 않습니다 !! )로 지정해도 상관하지 않기 때문에 작동합니다 .

그러나 유닉스 시스템에서는 대소 문자를 구분하지만 Windows 시스템에서는 대소 문자를 구분하는 데이터베이스 이름과 테이블 이름에는 동일하게 적용되지 않습니다 (아마도 많은 사람들이 밤에 깨어 있고 Windows에서 작업하지만 Linux에서 배포하는 사실은 :))


3
1. 사실 그것은 사실이 아닙니다. 열 이름은 사용중인 데이터베이스의 구성에 따라 대소 문자를 구분할 수 있습니다 ... 2. @Column 이름-이름에서 알 수 있듯이 프레임 워크의 식별자가 아닌 데이터베이스 열 이름을 제공하는 장소 여야합니다. 런타임 중에 변경됩니다.
Kamil

1. 감사합니다. 열 이름이 기본적으로 대소 문자를 구분하는 db의 예를 제공 할 수 있습니까? 2. 실제로 @Column은 PhysicalNamingStrategy에 의해 물리적 이름으로 해석되는 논리적 이름을 제공합니다. 최소한 문서가 말하는 것처럼 보입니다. docs.jboss.org/hibernate/orm/5.1/userguide/html_single/chapters/…
Orhan

2
1. 미안하지만 기본적으로 어떤 것이 있는지는 상관 없으므로 DBA가 사용중인 설정에 대해 어떤 설정을 지정했는지 관심이 있습니다. 2. 안타깝게도 사실입니다.이 접근 방식은 제가 생각하게하거나 이름이 마지막에 열에 매핑되는 방식 또는 제공된 이름을 건드리지 않는 어떤 이름 지정 전략을 사용해야하는지에 대해 생각하게하기 때문에 제 개인적인 의견입니다.
Kamil

1
사실, 그것은 가장 직관적 인 해결책이 될 것이며 물론 이것에 대한 더 나은 문서화는 해를 끼치 지 않을 것입니다.
Orhan

명시 적으로 설정된 열 이름은 모든 조건에서 암시 적으로 생성 된 이름을 재정의해야합니다. 그렇지 않은 경우 JPA 구현의 버그입니다.
jwenting

13

나를 위해 일한 유일한 솔루션은 위의 teteArg가 게시 한 솔루션이었습니다. 나는 Spring Boot 1.4.2 w / Hibernate 5에 있습니다. 즉

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)

6

teteArg , 정말 감사합니다. 정보 만 추가하면이 질문에 부딪히는 모든 사람이 그 이유를 이해할 수 있습니다.

무엇 teteArg는 봄 부팅 공용 속성에 표시되어 말했다 : http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html

분명히 spring.jpa.hibernate.naming.strategy 는 Hibernate 5를 사용하는 Spring JPA 구현을 위해 지원되는 속성이 아닙니다.


임 행복은 당신을 도울
teteArg

4

내가 변환해야한다는 것이 밝혀졌습니다. @column처음에는 카멜 케이스 였기 때문에 testName이라는 이름을 모두 소문자 하면됩니다.

공식 답변을 사용할 수는 없었지만 조사해야 할 사항을 알려줌으로써 문제를 해결하는 데 도움이 될 수있었습니다.

변화:

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

에:

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

3

@Column (...)을 사용하려면 실제 DB 열이 카멜 케이스 인 경우에도 항상 소문자를 사용하십시오.

예 : 실제 DB 열 이름이 TestName다음을 사용하는 경우 :

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

마음에 들지 않으면 실제 DB 열 이름을 test_name으로 변경하십시오.


1

필자의 경우 주석은 필드 자체 (레거시 애플리케이션에서 이식 됨) 대신 getter () 메서드에있었습니다.

Spring은이 경우에도 주석을 무시하지만 불평하지 않습니다. 해결책은 게터 대신 필드로 옮기는 것이 었습니다.


1
업데이트 주셔서 감사합니다. 참으로 귀중한 정보.
jwenting
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.