Проблема с именованием полей Hibernate с помощью Spring Загрузка (стратегия именования)
Обратите внимание, что этот код работает с обычным Spring, но не с Spring Boot (v1.3.3), есть что-то, чего я не вижу, потому что он импортируется из приложения Spring, которое работает. Ниже приведен код из загрузочного приложения Spring
@Entity
@Table(name="project")
public class Project implements Serializable{
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="id")
private int id;
@Column(name="teamId")
private int teamId;
//private String Rentabiliteit;
@Column
//@Index(name="IProject_status",columnNames="Status")
private String status;
@Column
//@Index(name="IProject_naam",columnNames="Naam")
private String naam;
//public Prototype m_Prototype;
//public Team m_Team;
}
SQL
CREATE TABLE IF NOT EXISTS `project` (
`id` int(11) NOT NULL,
`teamId` int(11) DEFAULT NULL,
`status` varchar(255) DEFAULT NULL,
`naam` varchar(255) DEFAULT NULL
) ENGINE=InnoDB AUTO_INCREMENT=43 DEFAULT CHARSET=latin1;
ОШИБКА
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException:
Unknown column 'project0_.team_id' in 'field list'
Отредактировано: Application.yml
spring:
mvc:
view:
prefix: /WEB-INF/jsp/
suffix: .jsp
datasource:
url: jdbc:mysql://localhost:3306/oxyplast
username: oxyplastuser
password: oxyplastuserpw
jpa:
properties:
hibernate:
current_session_context_class: org.springframework.orm.hibernate4.SpringSessionContext
namingStrategy: org.hibernate.cfg.DefaultNamingStrategy
Ответы
Ответ 1
Spring Boot предоставляет ImprovedNamingStrategy
качестве стратегии именования по умолчанию, которая позволяет Hibernate искать столбец team_id
(выводится из поля int teamId
). Поскольку этот столбец не существует в вашей таблице, это причина ошибки. Из документов Hibernate:
Улучшенная стратегия именования, которая предпочитает встроенные подчеркивания смешанным именам
У вас есть два варианта:
-
Укажите имя столбца в явном виде как @Column(name="teamId")
. Раньше была ошибка с этим в ранних версиях Boot, больше нет.
-
Измените стратегию именования в свойствах Spring Boot и попросите его использовать EJB3NamingStrategy
, который не конвертирует camelCase в snake_case, но сохраняет его как есть.
Обновить
Начиная с версии 1.4, из-за перехода на Hibernate 5 стратегия именования была обновлена до SpringPhysicalNamingStrategy
которая должна быть очень близка к значениям по умолчанию 1.3.
Смотрите также:
Ответ 2
Ниже стратегия работала для меня
spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.DefaultComponentSafeNamingStrategy
Ответ 3
с поздней версией:
spring-boot-starter-data-jpa: ➡ 1.5.2.RELEASE
hibernate-core:5.0.12.Final
этот класс
PhysicalNamingStrategyStandardImpl
необходимо расширить и добавить в свойства спящего режима.
Вот полная рабочая версия
public class PhysicalNamingStrategyImpl extends PhysicalNamingStrategyStandardImpl implements Serializable {
public static final PhysicalNamingStrategyImpl INSTANCE = new PhysicalNamingStrategyImpl();
@Override
public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment context) {
String nameModified;
// Do whatever you want with the name modification
return new Identifier(nameModified, name.isQuoted());
}
}
@Override
public Identifier toPhysicalColumnName(Identifier name, JdbcEnvironment context) {
String nameModified;
// Do whatever you want with the name modification
return new Identifier(nameModified, name.isQuoted());
}
Связывание с hibernate должно выполняться следующим образом при настройке источника данных.
properties.put("hibernate.physical_naming_strategy", "my.Package.PhysicalNamingStrategyImpl");
Вот полная рабочая версия конфигурации datasource
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef = "entityManagerFactory",
basePackages = { "com.xxxxxx.repository" }
)
public class SharedDataSourceConfig {
@Value("${startup.ddl-auto}")
String hbm2ddl;
@Primary
@Bean(name = "dataSource")
@ConfigurationProperties("spring.datasource.shared")
public DataSource customerDataSource() {
return DataSourceBuilder.create().build();
}
@Primary
@Bean(name = "entityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
EntityManagerFactoryBuilder builder,
@Qualifier("dataSource") DataSource dataSource) {
Map<String, Object> properties = new HashMap<String, Object>();
properties.put("hibernate.hbm2ddl.auto", hbm2ddl);
properties.put("hibernate.physical_naming_strategy", "my.package.PhysicalNamingStrategyImpl");
return builder
.dataSource(dataSource)
.packages(PackageScannerHelper.getPackagesToScan())
.persistenceUnit("shared")
.properties(properties)
.build();
}
@Primary
@Bean(name = "transactionManager")
public PlatformTransactionManager transactionManager(
@Qualifier("entityManagerFactory") EntityManagerFactory
entityManagerFactory
) {
return new JpaTransactionManager(entityManagerFactory);
}
}
Ответ 4
Если вы используете Spring Boot 2.0.2 и Hibernate 5.3.4, то установка следующего свойства решит проблему.
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
Ответ 5
Если вы используете Spring Boot 2.0.2 и Hibernate 5.3.4, то при установке следующего свойства в hibernate будут использоваться имена столбцов базы данных camelCase.
spring.jpa.hibernate.naming.physical-стратегия = org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
-damodar
Ответ 6
если вы хотите использовать UpperCase в имени столбца, вы должны использовать его таким образом
@Column(name="\"teamId\"")
private int teamId;
вам нужно принудительно спящий режим, даже используя EJB3NamingStrategy или ImprovedStrategyNaming.