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

如何为数据库分区表定义JPA实体,解决IDENTITY字段插入报错问题

问题原因

JPA规范仅支持将@GeneratedValue注解标注在实体类直接声明的@Id字段上,放在@Embeddable复合主键类内部的字段上不会被识别,因此你之前的配置没有生效,Hibernate仍然把entity_key_map_id当做普通主键字段处理,插入时传入null值触发了数据库报错。


解决方案

方案1:使用JPA标准@IdClass实现复合主键(推荐,无框架依赖)

  1. 改造主键类EntityKeyMapPK,移除所有JPA注解,只保留基础字段、无参构造、equals/hashCode重写、getter/setter:
import java.io.Serializable;

public class EntityKeyMapPK implements Serializable {
    private Long entityKeyMapId;
    private EntityType systemEntityAlias;

    public EntityKeyMapPK() {}

    // 重写equals和hashCode,必须基于两个主键字段判断
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        EntityKeyMapPK that = (EntityKeyMapPK) o;
        return entityKeyMapId.equals(that.entityKeyMapId) && systemEntityAlias.equals(that.systemEntityAlias);
    }

    @Override
    public int hashCode() {
        int result = entityKeyMapId.hashCode();
        result = 31 * result + systemEntityAlias.hashCode();
        return result;
    }

    // getter和setter
    public Long getEntityKeyMapId() { return entityKeyMapId; }
    public void setEntityKeyMapId(Long entityKeyMapId) { this.entityKeyMapId = entityKeyMapId; }
    public EntityType getSystemEntityAlias() { return systemEntityAlias; }
    public void setSystemEntityAlias(EntityType systemEntityAlias) { this.systemEntityAlias = systemEntityAlias; }
}
  1. 改造实体类,使用@IdClass绑定主键类,将两个主键字段直接声明在实体类中,给自增字段标注@GeneratedValue:
import javax.persistence.*;

@Entity
@Table(name = "entity_key_map", schema = "integration")
@IdClass(EntityKeyMapPK.class)
public class EntityKeyMap {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "entity_key_map_id", nullable = false)
    private Long entityKeyMapId;

    @Id
    @Column(name = "system_entity_alias", nullable = false)
    private EntityType systemEntityAlias;

    // 以下原有业务字段保持不变,无需修改
    @Column(name = "business_entity_alias", nullable = false, length = 5)
    @JsonProperty("businessEntityAlias")
    private EntityType businessEntityAlias;

    @Column(name = "business_key_1", nullable = false)
    @JsonProperty("businessKey1")
    private String businessKey1;

    // 其余business_key_2~5、system_alias、system_key_1~5的原有注解和定义全部保留
    // ... 省略原有业务字段定义

    // 所有字段的getter和setter
}

方案2:保留@EmbeddedId(依赖Hibernate专有特性)

如果不想调整现有@EmbeddedId的结构,可以用Hibernate提供的@Generated注解标注自增字段,告诉Hibernate该字段由数据库插入时生成:

  1. 改造主键类EntityKeyMapPK:
import org.hibernate.annotations.Generated;
import org.hibernate.annotations.GenerationTime;
import javax.persistence.Column;
import javax.persistence.Embeddable;
import java.io.Serializable;

@Embeddable
public class EntityKeyMapPK implements Serializable {
    @Generated(GenerationTime.INSERT) // 新增:标注该字段插入时由数据库生成
    @Column(name = "entity_key_map_id", nullable = false, insertable = false, updatable = false)
    private Long entityKeyMapId;

    @Column(name = "system_entity_alias", nullable = false)
    private EntityType systemEntityAlias;

    // 原有equals、hashCode、getter、setter保持不变
    // ...
}
  1. 实体类无需修改,保持原有@EmbeddedId的定义即可。

插入操作注意事项

两种方案插入数据时都不需要给entityKeyMapId赋值,只需要填充systemEntityAlias和其他业务字段,持久化完成后Hibernate会自动将数据库生成的自增ID回写到实体对象中,生成的INSERT语句不会携带entity_key_map_id字段,和你手动编写的SQL效果一致。

内容的提问来源于stack exchange,提问作者suitej

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 01:27:00