Spring Boot 3.4.3升级后Hibernate ORM生成错误列名引发SQL语法异常求助
嘿,看了你的问题,这大概率是Spring Boot升级后Hibernate ORM的默认命名策略发生变化导致的!我之前也碰到过类似的列名映射坑,给你梳理下情况和解决办法:
问题情况
你升级到Spring Boot 3.4.3(对应Hibernate 6.6.8-Final)后,Hibernate生成的SQL里试图访问ab_cst_office_id列,但数据库里实际存在的是abcstofficeid,所以抛出了SQLGrammarException。而在之前的Spring Boot 3.2.3(Hibernate 6.4.4-Final)版本中完全正常,说明新版本的Hibernate对驼峰命名的属性列映射规则变了。
报错核心信息:
org.hibernate.exception.SQLGrammarException: JDBC exception executing SQL ERROR: column jlargco1_0.ab_cst_office_id does not exist Hint: Perhaps you meant to reference the column "jlargco1_0.abcstofficeid". Position: 1495] [n/a] at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:91) ~[hibernate-core-6.6.8.Final.jar:6.6.8.Final] ...(省略后续栈信息)
你的实体类关键代码:
@Entity @Getter @Setter @Table(schema = "newschema_dbo", name = "jncdestofficebcstoffice") public class JnLctnAtcRegionsGlobColtOffice { // ...其他属性 @ManyToOne(cascade = CascadeType.PERSIST) @JoinColumn(name="abCstOfficeId", referencedColumnName = "abCstOfficeId") private abCstOffice abCstOffice; @OneToOne(cascade = CascadeType.PERSIST) @JoinColumn(name="cdEstOfficeId", referencedColumnName = "cdEstOfficeId") private cdEstOffice cdEstOffice; }
问题根源
Hibernate 6.6.x版本调整了默认的物理命名策略:旧版本中,你写的@JoinColumn(name="abCstOfficeId")会被直接转成小写的abcstofficeid(和数据库列名匹配);但新版本默认会把驼峰命名的属性自动转换为蛇形命名(比如abCstOfficeId → ab_cst_office_id),这就和数据库里实际的列名不匹配了。
解决方案
这里给你几个可行的解决办法,按优先级推荐:
1. 显式指定数据库列名(最稳妥)
直接在@JoinColumn的name属性里写数据库实际存在的列名abcstofficeid,跳过Hibernate的命名转换:
@ManyToOne(cascade = CascadeType.PERSIST) @JoinColumn(name="abcstofficeid", referencedColumnName = "abCstOfficeId") private abCstOffice abCstOffice; @OneToOne(cascade = CascadeType.PERSIST) @JoinColumn(name="cdestofficeid", referencedColumnName = "cdEstOfficeId") // 对应修改数据库实际列名 private cdEstOffice cdEstOffice;
这个方法最直接,不管Hibernate后续版本怎么调整命名策略,都能保证映射正确。
2. 全局配置命名策略,保持旧版本行为
如果你不想逐个修改实体类,可以在Spring Boot配置文件里指定全局的物理命名策略,让Hibernate不再自动转换驼峰为蛇形:
- 若使用
application.properties:
# 使用Hibernate标准命名策略,完全按照注解指定的名称生成数据库列名 spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
- 若使用
application.yml:
spring: jpa: hibernate: naming: physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
这个配置会让Hibernate完全遵循你在@Column、@JoinColumn里指定的name值,不会做额外的格式转换。
3. 检查关联实体的主键映射
另外要确认关联实体abCstOffice的主键配置:它的abCstOfficeId属性对应的数据库列是不是abcstofficeid?如果是的话,referencedColumnName要写目标实体主键列的逻辑名称(也就是实体属性对应的@Column的name值),确保关联关系映射正确。
总结
优先推荐第一种方法,直接显式指定数据库列名,避免后续版本升级带来的类似问题;如果有大量实体需要修改,再考虑全局配置命名策略。
备注:内容来源于stack exchange,提问作者Divya Muruganantham

