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.