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

Hibernate单向一对一映射报错:IdentifierGenerationException空ID生成

问题根源

  1. PersonStatusEntity的@Id同时配置了@GeneratedValue和@MapsId,两者冲突:@MapsId指定ID来源于关联的Person实体,但@GeneratedValue又试图让数据库自增生成ID,导致Hibernate无法确定ID生成逻辑,最终抛出空ID异常。
  2. 单向一对一关系的维护方配置错误:未明确指定关系由PersonStatus侧维护,导致Hibernate无法将Person的ID传递给PersonStatus。

正确配置代码

PersonEntity.kt

@Entity(name = "Person")
class PersonEntity(
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    var id: Long? = null,

    val name: String,

    @OneToOne(
        mappedBy = "person", // 指定关系由PersonStatus的person字段维护
        cascade = [CascadeType.ALL],
        fetch = FetchType.LAZY,
        optional = false,
        orphanRemoval = true
    )
    var personStatus: PersonStatusEntity
)

PersonStatusEntity.kt

@Entity(name = "PersonStatus")
class PersonStatusEntity(
    @Id
    var id: Long? = null, // 移除@GeneratedValue,ID由关联的Person提供

    @OneToOne(fetch = FetchType.LAZY)
    @MapsId // 将当前实体的id与关联Person的id绑定
    var person: PersonEntity, // 改为非空,匹配Person中optional=false的约束

    @Enumerated(EnumType.STRING)
    val status: Status
)

正确保存方式

保存时必须先建立Person与PersonStatus的关联,再持久化Person(级联操作会自动保存PersonStatus):

val personStatus = PersonStatusEntity(status = Status.ACTIVE, person = null)
val person = PersonEntity(name = "测试用户", personStatus = personStatus)
personStatus.person = person // 建立关联,确保PersonStatus能获取到Person的ID

entityManager.persist(person)

表结构说明

如果要完全遵循Hibernate推荐的高效方案,person_status表不需要单独的person_id字段,直接用主键id作为外键关联person表的id即可,减少冗余字段提升性能。如果坚持保留person_id字段,@MapsId并不适用,此时应移除@MapsId,在PersonStatus的person字段上添加@JoinColumn(name = "person_id"),同时恢复PersonStatus的@Id上的@GeneratedValue配置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 05:15:35