Spring Boot + JPA: Sütun adı ek açıklaması yok sayıldı


121

Bağımlılığı olan bir Spring Boot uygulamam var spring-boot-starter-data-jpa. Varlık sınıfımın sütun adıyla bir sütun ek açıklaması var. Örneğin:

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

Bununla oluşturulan SQL test_name, sütun adı olarak oluşturulur . Bir çözüm spring.jpa.hibernate.naming_strategy=org.hibernate.cfg.EJB3NamingStrategyaradıktan sonra sorunun çözüldüğünü buldum (sütun adı sütun açıklamasından alınmıştır).

Yine de sorum şu ki, naming_strategy EJB3NamingStrategyJPA olarak ayarlanmadan sütun ek açıklamasını neden yok sayıyor ? Belki hazırda bekletme lehçesinin bununla bir ilgisi vardır? MS SQL 2014 Express'e bağlanıyorum ve günlüklerim şunları içeriyor:

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

1
Bu soru, açıkça sağlanan sütun adının göz ardı edilmek yerine değiştirilmesiyle ilgilidir . Bu aşağı kaynar bu yerine beklenen infaz varlık şeffaf varyantı . Hazırda bekletme, örneğin beklenenden farklı bir erişim türü kullandığınızda ek açıklamayı yok sayabilir , ancak burada durum böyle değildir. @Column(name="...")
— Vlastimil Ovčáčík

Yanıtlar:


163

Hibernate5 için application.properties dosyama sonraki satırları ekleyerek bu sorunu çözdüm:

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, adı olduğu gibi tutmak için yalnızca bu özellik gereklidir.
— abhishek Ringsia

1
Aynı sorunu yaşadım ve bu 2 özelliği eklemek benim için çözdü. Spring Boot 1.4.3'ü çalıştırıyorum
— Johan

1
Benim için de işe yarayan tek çözüm bu. Spring Boot 1.4.2 kullanıyorum
— Sanjiv Jivan

Spring Boot 1.5.9'u kullanıyorum. YAYIN, bu yazı benim için çalışıyor
— IcyBrk

Harika .. @Column ek açıklamamı neden yok saydığını merak ediyordum. Sonunda bu bana yardımcı oldu. Bana göre bunun bir hata veya eksik işlev olduğunu düşünüyorum.
— Raju Penumatsa

86

Spring, varsayılan org.springframework.boot.orm.jpa.SpringNamingStrategyolarak tablo adları oluşturmak için kullanır . Bu çok ince bir uzantısıdır org.hibernate.cfg.ImprovedNamingStrategy. Bu tableNamesınıftaki yönteme bir kaynak Stringdeğeri aktarılır, ancak bir @Column.nameöznitelikten mi yoksa örtük olarak alan adından mı üretildiğinden habersizdir .

ImprovedNamingStrategyDönüştürecektir CamelCaseiçin SNAKE_CASEolduğu gibi burada EJB3NamingStrategysadece değişmemiş tablo adını kullanır.

Adlandırma stratejisini değiştirmek istemiyorsanız, her zaman sütun adınızı küçük harfle belirtebilirsiniz:

@Column(name="testname")

1
Merhaba Phil. Spring boot kullanarak spring.jpa.hibernate.naming.strategy ekledim: org.hibernate.cfg.EJB3NamingStrategy. Ama benim için çalışmıyor gibi görünüyor. bana yardım eder misiniz?
— BeeNoisy

Cevabın önemli kısmı adı küçük harfle yazmaktır! Kategoriyi değiştirmemenizi tavsiye ederim, ancak sütun adı büyük / küçük harfe duyarlı olmadığından adın küçük harf olması önerilir!
— loicmathieu

31

Öyle görünüyor

@Column (isim = "..")

olmadığı sürece tamamen göz ardı edilir

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

benim için bu bir hatadır.

@Column'un (name = "..") neden göz ardı edildiğini anlamaya çalışırken birkaç saat geçirdim.


4
Ben de aynı sorunu yaşadım. Buraya bir sorun raporu ekledim: github.com/spring-projects/spring-boot/issues/2129
— Kacper86

Çok teşekkürler. Uygulamamı mevcut veritabanına yönlendirmek için yaklaşık bir gün kaybettim.
— Dmitry Erokhin

Aslında yok sayılmaz, yalnızca verilen ad özelliğine varsayılan yay adlandırma stratejisi uygulanır. @PhilWebb cevabını oku
— Michel Feldheim

16

İçin varsayılan strateji @Column(name="TestName")olacaktır test_name, bu doğru bir davranıştır!

TestNameVeritabanınızda adlandırılmış bir sütununuz varsa, Sütun ek açıklamasını olarak değiştirmelisiniz @Column(name="testname").

Bu işe yarar çünkü veritabanı, sütununuzu TestName veya testname olarak adlandırmanıza aldırmaz ( sütun adları büyük / küçük harfe duyarlı değildir !! ).

Ancak, Unix sistemlerinde büyük / küçük harfe duyarlı olan ancak Windows sistemlerinde büyük / küçük harfe duyarlı olan veritabanı adı ve tablo adları için de geçerli olmadığına dikkat edin (muhtemelen birçok insanı geceleri uyanık tutmuş, pencerelerde çalışıyor, ancak linux üzerinde konuşlandırıyor) :))


3
1. Aslında bu doğru değil, sütun adları, kullandığınız veritabanının yapılandırmasına bağlı olarak büyük / küçük harfe duyarlı olabilir ... 2. @Column name - adından da anlaşılacağı gibi veritabanı sütun adı sağlamak için bir yer olmalı, çerçevenin olduğu bir tanımlayıcı değil çalışma sırasında değişecek ..
— Kamil

1. Teşekkürler, sütun adlarının varsayılan olarak büyük / küçük harfe duyarlı olduğu bir db örneği verebilir misiniz? 2. Aslında @Column bize PhysicalNamingStrategy tarafından fiziksel adlara çözümlenen mantıksal isimler veriyor, en azından bu, dokümanın söylediği gibi görünüyor: docs.jboss.org/hibernate/orm/5.1/userguide/html_single/chapters/…
— Orhan

2
1. Özür dilerim, varsayılan olarak hangisinin sahip olduğu umrumda olmadığından, kullandığım cihazda DBA tarafından hangi ayarların yapıldığını umursuyorum. 2. Bu maalesef doğru - bu yaklaşımın yanlış olduğu, beni düşünmeye ya da adın sondaki sütuna nasıl eşleneceği ya da sağlanan adlara dokunmayan hangi adlandırma stratejisinin kullanılacağı konusunda beni düşünmeye zorluyor.
— Kamil

1
Doğru, bu en sezgisel çözüm olacaktır ve elbette bununla ilgili daha iyi dokümantasyon zarar vermez.
— Orhan

açıkça ayarlanmış bir sütun adı, tüm koşullar altında örtük olarak oluşturulmuş olanı geçersiz kılmalıdır. Değilse, bu JPA uygulamasında bir hatadır.
— 2019

13

Benim için işe yarayan tek çözüm yukarıda teteArg tarafından yayınlanan çözümdü. Spring Boot 1.4.2 w / Hibernate 5'teyim. Yani

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

Daha fazla içgörü için arama izini gönderiyorum, böylece Spring'in adlandırma stratejisini ayarlamak için Hazırda Bekletme'ye ne yaptığını netleştiriyorum.

      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 , çok teşekkür ederim. Sadece eklenmiş bir bilgi, bu yüzden bu soruyla karşılaşan herkes nedenini anlayabilecektir.

Ne teteArg Bahar Boot Ortak özellikler belirtilmiştir ki: http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html

Görünüşe göre spring.jpa.hibernate.naming.strategy , Hibernate 5 kullanan Spring JPA uygulaması için desteklenen bir özellik değil.


Size yardımcı olmaktan mutluluk duyuyorum
— teteArg

4

@columnBaşlangıçta deve durumunda olduğu için testName adını tüm küçük harflere dönüştürmek zorunda olduğum ortaya çıktı .

Resmi cevabı kullanamasam da, soru neyi araştırmam gerektiğini bildirerek sorunumu çözmeme yardımcı oldu.

Değişiklik:

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

Kime:

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

3

@Column (...) kullanmak istiyorsanız, gerçek DB sütununuz deve durumunda olsa bile her zaman küçük harf kullanın.

Örnek: Gerçek DB sütun adınız ise şunu TestNamekullanın:

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

Bundan hoşlanmıyorsanız, gerçek DB sütun adını şu şekilde değiştirin: test_name


1

Benim durumumda, ek açıklama alanın kendisi yerine getter () yöntemindeydi (eski bir uygulamadan taşınmıştır).

Spring bu durumda da açıklamayı görmezden geliyor ama şikayet etmiyor. Çözüm, alıcı yerine sahaya taşımaktı.


1
Güncelleme için teşekkürler. Gerçekten değerli bilgiler.
— 2019
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.