Spring Boot + JPA: аннотацию имени столбца игнорируется

У меня есть приложение Spring Boot с зависимостью spring-boot-starter-data-jpa. У моего класса сущности есть аннотация столбца с именем столбца. Например:

@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 

Ответ 1

Для 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

Ответ 2

По умолчанию Spring использует org.springframework.boot.orm.jpa.SpringNamingStrategy для генерации имен таблиц. Это очень тонкое расширение org.hibernate.cfg.ImprovedNamingStrategy. Метод tableName в этом классе передается исходным значением String, но он не знает, исходит ли он из атрибута @Column.name или если он неявно генерируется из имени поля.

ImprovedNamingStrategy преобразует CamelCase в SNAKE_CASE, где, поскольку EJB3NamingStrategy просто использует имя таблицы без изменений.

Если вы не хотите менять стратегию именования, вы всегда можете просто указать имя столбца в нижнем регистре:

@Column(name="testname")

Ответ 3

Кажется, что

@Column (name= ".." )

полностью игнорируется, если не существует

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

поэтому для меня это ошибка.

Я потратил несколько часов, пытаясь понять, почему @Column (name= ".." ) был проигнорирован.

Ответ 4

Единственное решение, которое сработало для меня, было тем, что было опубликовано 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)

Ответ 5

Стратегия по умолчанию для @Column(name="TestName") будет test_name, это правильное поведение!

Если у вас есть столбец с именем TestName в вашей базе данных, вы должны изменить аннотацию столбца на @Column(name="TestName").

Это работает, потому что базе данных все равно, назовете ли вы имя столбца TestName или testname (имена столбцов нечувствительны к регистру!!).

Но будьте осторожны, то же самое не относится к именам баз данных и таблицам, которые чувствительны к регистру в Unix-системах, но с учетом чувствительности к системам Windows (тот факт, что, вероятно, многие люди просыпались ночью, работая над окнами, но развертывание на Linux:))

Ответ 6

teteArg, большое вам спасибо. Просто добавленная информация, поэтому все, кто сталкивается с этим вопросом, смогут понять, почему.

Что teteArg указано в Spring Общие свойства загрузки: < а2 >

По-видимому, spring.jpa.hibernate.naming.strategy не является поддерживаемым свойством для реализации Spring JPA с использованием Hibernate 5.

Ответ 7

Единственное, что сработало для меня, это наличие двух строк кода, как указано выше:

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

Только одна линия, предложенная ncaralicea, не работала для меня

Ответ 8

Если вы хотите использовать @Column (...), всегда используйте строчные буквы, даже если ваш фактический столбец БД находится в верблюжьем регистре.

Пример: если ваше фактическое имя столбца БД - TestName используйте:

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

Если вам это не нравится, просто измените фактическое имя столбца БД на: test_name

Ответ 9

В моем случае, аннотация была на методе getter() вместо самого поля (перенесено из унаследованного приложения).

Spring игнорирует аннотацию и в этом случае, но не жалуется. Решение состояло в том, чтобы переместить это в область вместо добытчика.

Ответ 10

Оказывается, мне просто нужно преобразовать @column name testName во все строчные буквы, так как изначально это было в случае верблюда.

Хотя я не смог использовать официальный ответ, этот вопрос помог мне решить мою проблему, сообщив мне, что нужно расследовать.

Изменить:

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

Для того, чтобы:

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