Spring Boot 的 Hibernate 字段命名问题(命名策略)
Posted
技术标签:
【中文标题】Spring Boot 的 Hibernate 字段命名问题(命名策略)【英文标题】:Hibernate field naming issue with Spring Boot (naming strategy) 【发布时间】:2020-06-06 20:56:24 【问题描述】:请注意,此代码确实适用于普通 Spring,但不适用于 Spring Boot(v1.3.3),我是否缺少某些东西,因为这是从有效的 spring 应用程序导入的。下面的代码来自spring boot app
@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
【问题讨论】:
我怀疑问题是否出在您发布的代码中。你能发布完整的堆栈跟踪吗? github.com/thibitus/SE4-Oxyplast/tree/master/OxyplastSpringBoot @MadhusudanaReddySunnapu 这太长了,但我这是造成问题的原因 查看了域包。 Project 是唯一被注释为实体的类。剩下的都是普通班。这是正确的吗?您可以发布其中包含根本原因字符串的部分堆栈跟踪吗? 这个github线程很有用:github.com/spring-projects/spring-boot/issues/2129 【参考方案1】:自 SPRING-BOOT 1.4 以来
从 1.4 开始,由于切换到 Hibernate 5,命名策略已更新为 SpringPhysicalNamingStrategy
其中should be very close 为 1.3 默认值。
另请参阅:
Spring's naming strategy以前的版本
Spring Boot 提供 ImprovedNamingStrategy
作为默认命名策略,这使得 Hibernate 搜索 team_id
列(从 int teamId
字段推断)。由于您的表中不存在此列,因此这是错误的原因。来自 Hibernate 文档:
一种改进的命名策略,它更喜欢嵌入下划线而不是混合大小写名称
你有两个选择:
明确提供列名为@Column(name="teamId")
。在早期的 Boot 版本中曾经有一个 bug,现在没有了。
在 Spring Boot 属性中更改命名策略,并告诉它使用EJB3NamingStrategy
,它不会将camelCase 转换为snake_case,而是保持原样。 p>
【讨论】:
我提供了明确的列名,它可以被 hiberante 以不同的方式映射吗?有没有办法看到这个? 在我的 application.yml 中有这一行 我已经通过将其重命名为 teamid(不带大写 I)解决了这个问题!非常感谢您的参与和帮助 添加这些属性为我解决了这个问题:--spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl --spring.jpa.hibernate.naming .physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl 我通过在文件 application.properties 中添加这一行来解决问题:spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl【参考方案2】:以下策略对我有用
spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.DefaultComponentSafeNamingStrategy
【讨论】:
spring.jpa.hibernate.naming-strategy 在最新版本中不存在此解决方案可能有效但不会在最新版本中。【参考方案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());
在配置数据源时应该像这样将它链接到休眠状态。
properties.put("hibernate.physical_naming_strategy", "my.Package.PhysicalNamingStrategyImpl");
这是数据源配置的完整工作版本
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
【讨论】:
我在我的项目中尝试了同样的方法,但它不起作用。我已在此链接***.com/questions/61010482/… 中发布了我的问题【参考方案5】:这对我来说适用于 spring boot 1.4.0 和 hibernate entitymanager 4.3.8.Final
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
【讨论】:
【参考方案6】:application.properties
spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.DefaultComponentSafeNamingStrategy
以上属性对我有用。 休眠 4.3.11.Final spring boot 1.4.2.RELEASE
【讨论】:
以上是关于Spring Boot 的 Hibernate 字段命名问题(命名策略)的主要内容,如果未能解决你的问题,请参考以下文章
制作多个 EntityManager(Spring-Boot-JPA、Hibernate、MSSQL)
Hibernate 和 CRUDRepository Spring Boot