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="...")
VlastimilOvčáčík2016年

回答:


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 ringia 2016年

1
私は同じ問題を抱えていて、それら2つのプロパティを追加することで解決しました。Spring Boot 1.4.3を実行しています
Johan

1
これも私にとって有効な唯一の解決策です。私はSpring Boot 1.4.2を使用しています
Sanjiv Jivan

私はSpring Boot 1.5.9.RELEASEを使用しています。この投稿は私にとって
役に立ち

すばらしい.. @Columnアノテーションがなぜ無視されているのかと思っていました。最後にこれは私を助けました。私には、これはバグであるか、機能が不足しているように感じます。
Raju Penumatsa

86

デフォルトでは、Springはorg.springframework.boot.orm.jpa.SpringNamingStrategyテーブル名の生成に使用します。これはの非常に薄い拡張ですorg.hibernate.cfg.ImprovedNamingStrategytableNameそのクラスのメソッドにはソースString値が渡されますが、@Column.name属性からのものか、フィールド名から暗黙的に生成されたものかはわかりません。

ImprovedNamingStrategy変換するCamelCaseSNAKE_CASE通りであるEJB3NamingStrategyだけでそのままテーブル名を使用しています。

名前付け戦略を変更したくない場合は、常に列名を小文字で指定するだけです。

@Column(name="testname")

1
こんにちは、フィル。スプリングブートを使用して、spring.jpa.hibernate.naming.strategy:org.hibernate.cfg.EJB3NamingStrategyを追加しました。しかし、私にはうまくいかないようです。手伝って頂けますか?
BeeNoisy 2017年

応答の重要な部分は、名前を小文字にすることです!私はstategyを変更しないことをお勧めしますが、列名は大文字と小文字を区別しないため、名前を付けるのは小文字です!
loicmathieu

31

のようだ

@Column(name = "..")

ない限り完全に無視されます

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

指定されたので、私にとってこれはバグです。

@Column(name = "..")が無視された理由を理解するために数時間を費やしました。


4
私も同じ問題を抱えていました。ここに問題レポートを追加しました:github.com/spring-projects/spring-boot/issues/2129
Kacper86

どうもありがとう。アプリを既存のデータベースにポイントするために約1日失われました。
Dmitry Erokhin

実際には無視されません。指定された名前属性にデフォルトのスプリング命名戦略が適用されるだけです。@PhilWebbの回答を読む
ミシェルフェルドハイム

15

のデフォルトの戦略@Column(name="TestName")はですtest_name。これは正しい動作です!

TestNameデータベースで名前が付けられた列がある場合は、列注釈をに変更する必要があります@Column(name="testname")

これは、列にTestNameまたはtestnameという名前を付けてもデータベースが気にしないため機能します(列名は大文字と小文字を区別しません!!)。

ただし、同じことがデータベース名とテーブル名には適用されません。これらは、Unixシステムでは大文字と小文字が区別されますが、Windowsシステムでは大文字と小文字が区別されます(おそらく、多くの人が夜に目を覚まし、Windowsで作業しているがLinuxで展開しているためです)。 :))


3
1.実際にはそうではありません。使用しているデータベースの構成によっては、列名で大文字と小文字が区別される場合があります... 2. @列名-名前が示すように、フレームワークの識別子ではなく、データベースの列名を指定する場所です実行時に変更されます...
カミル

1.おかげで、列名でデフォルトで大文字と小文字が区別されるdbの例を挙げられますか?2.実際に@Columnは私たちにPhysicalNamingStrategyによって物理名に解決される論理名を与え、少なくとも、それは、docが言うことのようです:docs.jboss.org/hibernate/orm/5.1/userguide/html_single/chapters/...
オルハンを

2
1.申し訳ありませんが、デフォルトでどちらが設定されているかは気にしないので、DBAが使用している設定をどのように設定するかは気にしません。2.それは残念ながら本当です-このアプローチが間違っているというのは私の個人的な意見ですが、名前を最後に列にマッピングする方法や、指定された名前に影響を与えない使用する命名戦略について考えるように強いられます。
カミル2017年

1
確かに、それは最も直感的な解決策であり、もちろんこれに関するより優れたドキュメントは害にはなりません。
Orhan

明示的に設定された列名は、すべての条件下で暗黙的に生成された列名をオーバーライドする必要があります。そうでない場合は、JPA実装のバグです。
13:07に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 2017

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.