Spring Boot + JPA: annotazione del nome della colonna ignorata

Ho un’applicazione Spring Boot con dipendenza spring-boot-starter-data-jpa . La mia class di quadro ha un’annotazione di colonna con un nome di colonna. Per esempio:

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

SQL generato da questo nome test_name creato come nome delle colonne. Dopo aver cercato una soluzione, ho trovato che spring.jpa.hibernate.naming_strategy=org.hibernate.cfg.EJB3NamingStrategy risolto il problema (il nome della colonna è preso dall’annotazione della colonna).

Tuttavia, la mia domanda è: perché senza naming_strategy impostato su EJB3NamingStrategy JPA sta ignorando l’annotazione della colonna? Forse il dialetto in letargo ha qualcosa a che fare con esso? Mi sto collegando a MS SQL 2014 Express e i miei registri contengono:

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

Per hibernate5 ho risolto questo problema inserendo le righe seguenti nel mio file 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 

Per impostazione predefinita, Spring utilizza org.springframework.boot.orm.jpa.SpringNamingStrategy per generare nomi di tabelle. Questa è un’estensione molto sottile di org.hibernate.cfg.ImprovedNamingStrategy . Il metodo tableName in quella class viene passato un valore di String origine ma non è consapevole se proviene da un attributo @Column.name o se è stato generato implicitamente dal nome del campo.

ImprovedNamingStrategy convertirà CamelCase in SNAKE_CASE dove come EJB3NamingStrategy usa semplicemente il nome della tabella invariato.

Se non si desidera modificare la strategia di denominazione, è sempre ansible specificare il nome della colonna in lettere minuscole:

 @Column(name="testname") 

Sembra che

@Column (name = “..”)

è completamente ignorato a meno che non ci sia

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

specificato, quindi per me questo è un bug.

Ho passato alcune ore a cercare di capire perché @Column (name = “..”) è stato ignorato.

L’unica soluzione che ha funzionato per me è stata quella postata da teteArg sopra. Sono su Spring Boot 1.4.2 con Hibernate 5. Vale a dire

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

Per ulteriori informazioni, sto postando la traccia della chiamata in modo che sia chiaro che cosa sta chiamando Spring in Hibernate per impostare la strategia di denominazione.

  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 , grazie mille. Solo un’informazione aggiunta, quindi, chiunque si imbattesse in questa domanda sarà in grado di capire perché.

Quello che teteArg ha detto è indicato nelle Proprietà comuni di Spring Boot: http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html

Apparentemente, spring.jpa.hibernate.naming.strategy non è una proprietà supportata per l’implementazione Spring JPA che utilizza Hibernate 5.

L’unica cosa che ha funzionato per me era avere entrambe le righe di codice come postate sopra:

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

Avere solo la linea singola proposta da ncaralicea non ha funzionato per me

La strategia predefinita per @Column(name="TestName") sarà test_name , questo è il comportamento corretto!

Se nel database è presente una colonna denominata TestName è necessario modificare l’annotazione della colonna in @Column(name="testname") .

Funziona perché al database non interessa se si assegna un nome alla colonna TestName o testname (i nomi delle colonne sono case insensitive !! ).

Ma attenzione, lo stesso non si applica ai nomi di database e nomi di tabelle, che fanno distinzione tra maiuscole e minuscole su sistemi Unix ma case sensitive su sistemi Windows (il fatto che probabilmente teneva molte persone sveglie di notte, lavorando su Windows ma distribuendo su Linux :))

Se si desidera utilizzare @Column (…), utilizzare sempre lettere minuscole anche se la colonna DB attuale è in caso cammello.

Esempio: se il nome effettivo della colonna DB è: TestName, utilizzare:

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

Se non ti piace, cambia semplicemente il nome effettivo della colonna DB in: test_name