You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot+PostgreSQL使用DataSource无法保存实体对象问题求助

解决Spring Boot + PostgreSQL无法保存实体的问题

看起来你遇到的问题是插入实体后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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:39:50