依存関係spring-boot-starter-data-jpa
のSpring Bootアプリケーションがあります。エンティティクラスには、列名を持つ列注釈があります。例えば:
@Column(name="TestName")
private String testName;
これによって生成されたSQLは、列名としてtest_name
を作成しました。解決策を探した後、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
は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(name="testname")
に変更する必要があります。
これは、列にTestNameまたはtestnameという名前を付けてもデータベースが気にしないためです(列名は大文字と小文字を区別しません!!)。
ただし、Unixシステムでは大文字と小文字が区別されますが、Windowsシステムでは大文字と小文字が区別されるデータベース名とテーブル名には同じことが当てはまりません:))
私のために働いた唯一の解決策は、上記の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)
teteArg 、ありがとうございました。追加情報なので、この質問にぶつかった人は誰でもその理由を理解できます。
teteArg が言ったことは、Spring Bootの共通プロパティに示されています: http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties .html
明らかに、spring.jpa.hibernate.naming.strategyは、Hibernate 5を使用したSpring JPA実装でサポートされているプロパティではありません。
@Column(...)を使用する場合は、実際のDB列がキャメルケースであっても、常に小文字を使用します。
例:実際のDB列名がTestName
の場合、次を使用します。
@Column(name="testname") //all small-case
気に入らない場合は、実際のDB列名をtest_nameに変更するだけです
@column
name testNameをすべて小文字に変換する必要があることがわかりました。最初はラクダの場合でした。
公式の回答を使用することはできませんでしたが、この質問は、調査対象を知らせることで問題の解決に役立ちました。
変化する:
@Column(name="testName")
private String testName;
に:
@Column(name="testname")
private String testName;
私の場合、注釈はフィールド自体(従来のアプリケーションから移植された)ではなくgetter()メソッドにありました。
この場合もSpringは注釈を無視しますが、文句は言いません。解決策は、ゲッターではなくフィールドに移動することでした。