Spring Boot+PostgreSQL使用DataSource无法保存实体对象问题求助
看起来你遇到的问题是插入实体后Hibernate无法获取自增的encoderId,导致报"The column name 'encoderId' was not found in this ResultSet"错误。虽然查询和删除能正常工作,但插入时的ID获取环节出了问题,根源在于PostgreSQL对大小写敏感的标识符处理,以及Hibernate的命名策略配合问题。
问题分析
PostgreSQL默认会把不带引号的标识符转为小写,而你的表和列都是驼峰命名,所以必须用双引号包裹才能识别。你当前的实体里给列名加了"encoderId"这样的引号,插入SQL是正确的,但Hibernate在插入后尝试从ResultSet中获取生成的ID时,可能用的是小写的encoderid去查找,而ResultSet里的列名是驼峰的encoderId,所以匹配失败。
解决方案
推荐使用自定义Hibernate物理命名策略,自动给所有表名和列名加上双引号,这样既能保持驼峰命名,又能让Hibernate在所有SQL操作(包括插入后的ID获取)中正确识别标识符。
1. 自定义物理命名策略类
创建一个类继承PhysicalNamingStrategyStandardImpl,重写表名和列名的处理逻辑,自动添加双引号:
package com.yourpackage; // 替换成你的实际包名 import org.hibernate.boot.model.naming.Identifier; import org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl; import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; public class QuotedCamelCaseNamingStrategy extends PhysicalNamingStrategyStandardImpl { @Override public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment context) { return wrapInQuotes(name); } @Override public Identifier toPhysicalColumnName(Identifier name, JdbcEnvironment context) { return wrapInQuotes(name); } private Identifier wrapInQuotes(Identifier name) { if (name == null || name.isQuoted()) { return name; } return new Identifier("\"" + name.getText() + "\"", true); } }
2. 修改配置文件
更新application.properties里的Hibernate命名策略,替换为你自定义的类:
spring.datasource.driverClassName=org.postgresql.Driver spring.datasource.url=jdbc:postgresql://localhost:5432/encoderDb spring.datasource.initialize=true spring.datasource.username=user spring.datasource.password=password spring.jpa.generate-ddl=false # 替换为自定义的命名策略类路径 spring.jpa.hibernate.naming.physical-strategy=com.yourpackage.QuotedCamelCaseNamingStrategy spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
3. 简化实体类注解
现在可以去掉实体类里@Table和@Column中的引号,直接写驼峰名称即可:
@Entity @Table(name="TableEncoder") public class TableEncoder implements Serializable { @Id @Column(name="encoderId") @GeneratedValue(strategy=GenerationType.IDENTITY) private Integer encoderId; @Column(name="aspectRatio") private String aspectRatio; @Column(name="audioBitRate") private Integer audioBitRate; // 记得添加无参构造器、getter和setter方法 }
额外检查
- 确认数据库中
TableEncoder表的encoderId列是自增类型(比如SERIAL或IDENTITY),否则GenerationType.IDENTITY无法正常工作。 - 确保实体类有无参构造器,这是JPA规范要求的必要条件。
这样调整后,Hibernate生成的所有SQL都会给表名和列名加上双引号,PostgreSQL能正确识别驼峰命名,插入后也能正确获取生成的ID,保存操作就可以正常执行了。
内容的提问来源于stack exchange,提问作者Vishnu Viswambharan

