web-dev-qa-db-fra.com

Spring Boot + JPA: annotation du nom de la colonne ignorée

J'ai une application Spring Boot avec dépendance spring-boot-starter-data-jpa. Ma classe d'entités comporte une annotation de colonne avec un nom de colonne. Par exemple:

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

Le code SQL généré par ceci a créé test_name en tant que nom de colonne. Après avoir cherché une solution, j'ai découvert que spring.jpa.hibernate.naming_strategy=org.hibernate.cfg.EJB3NamingStrategy avait résolu le problème (le nom de colonne est tiré de l'annotation de colonne).

Néanmoins, ma question est la suivante: pourquoi, sans naming_strategy défini sur EJB3NamingStrategy, JPA ignore les annotations de colonne? Peut-être que le dialecte en veille prolongée a quelque chose à voir avec cela? Je me connecte à MS SQL 2014 Express et mes journaux contiennent:

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

Pour hibernate5, j'ai résolu ce problème en ajoutant les lignes suivantes dans mon fichier 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
133
teteArg

Par défaut, Spring utilise org.springframework.boot.orm.jpa.SpringNamingStrategy pour générer les noms de table. C'est une extension très fine de org.hibernate.cfg.ImprovedNamingStrategy. La méthode tableName de cette classe reçoit une valeur source String, mais elle ignore si elle provient d'un attribut @Column.name ou si elle a été générée de manière implicite à partir du nom du champ.

Le ImprovedNamingStrategy convertira CamelCase en SNAKE_CASE où, comme EJB3NamingStrategy, il utilisera simplement le nom de la table sans modification.

Si vous ne souhaitez pas modifier la stratégie de dénomination, vous pouvez toujours spécifier votre nom de colonne en minuscule:

@Column(name="testname")
79
Phil Webb

Il paraît que

@Column (name = "..")

est complètement ignoré sauf s'il y a

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

spécifié, donc pour moi c'est un bug.

J'ai passé quelques heures à essayer de comprendre pourquoi @Column (name = "..") était ignoré.

31
ncaralicea

La stratégie par défaut pour @Column(name="TestName") sera test_name, il s'agit d'un comportement correct!

Si vous avez une colonne nommée TestName dans votre base de données, vous devez changer l'annotation de colonne en @Column(name="testname").

Cela fonctionne parce que la base de données ne vous intéresse pas si vous nommez votre colonne NomTest ou nomTest (les noms de colonne ne sont pas sensibles à la casse !!).

Mais attention, il en va de même pour les noms de base de données et de table, qui sont sensibles à la casse sur les systèmes Unix mais sensibles à la casse sur les systèmes Windows (le fait que beaucoup de gens aient probablement veillé la nuit, travaillant sous Windows mais se déployant sous Linux :))

11
Orhan

La seule solution qui a fonctionné pour moi était celle publiée par teteArg ci-dessus. Je suis sur Spring Boot 1.4.2 avec Hibernate 5. À savoir

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

Pour plus d'informations, je publie la trace des appels de manière à indiquer clairement ce que Spring appelle dans Hibernate pour configurer la stratégie de dénomination.

      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)
9
Sanjiv Jivan

teteArg , merci beaucoup. Juste une information supplémentaire donc, tout le monde se cogner à cette question sera en mesure de comprendre pourquoi.

Ce que teteArg dit est indiqué dans les propriétés communes du démarrage initial: http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties .html

Apparemment, spring.jpa.hibernate.naming.strategy n'est pas une propriété prise en charge pour l'implémentation Spring JPA avec Hibernate 5.

6
Romeo Jr Maranan

Si vous souhaitez utiliser @Column (...), utilisez toujours des lettres minuscules, même si votre colonne de base de données est en camel.

Exemple: Si votre nom de colonne de base de données actuel est TestName, utilisez:

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

Si vous n'aimez pas cela, changez simplement le nom de colonne actuel de la base de données en: nom_test

3
Dean

Il s'avère que je dois juste convertir @column nom testName en lettres minuscules, car il s'agissait initialement d'une casse de chameau.

Bien que je n’aie pas pu utiliser la réponse officielle, la question a été en mesure de m'aider à résoudre mon problème en me laissant savoir quoi enquêter.

Changement:

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

À:

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

Dans mon cas, l'annotation était sur la méthode getter () au lieu du champ lui-même (porté à partir d'une application héritée).

Spring ignore également l'annotation dans ce cas, mais ne se plaint pas. La solution consistait à le déplacer sur le terrain au lieu du getter.

0
java-addict301