JPA中单向OneToMany关联与复合主键配置问题
解决JPA复合主键(parent_id + application)的实现方案
步骤1:定义复合主键类
创建@Embeddable类型的复合主键类,包含parentId和application两个字段,同时实现Serializable接口(JPA强制要求):
@Embeddable data class ChildId( val parentId: Long, val application: String ) : Serializable
步骤2:修改ChildEntity实体
用@EmbeddedId替换原来的单一@Id,将复合主键作为实体的主键,移除原有的单独application字段:
@Entity(name = "child") data class ChildEntity( @EmbeddedId val id: ChildId, @Column(name = "tag") val tag: String? = null )
步骤3:调整ParentEntity的关联关系
修改@OneToMany注解,通过mappedBy关联到子实体主键中的parentId字段,同时添加orphanRemoval = true实现“更新时先删再存”的需求:
@Entity(name = "parent") data class ParentEntity( @Id var id: Long? = null, @OneToMany( mappedBy = "id.parentId", cascade = [CascadeType.ALL], fetch = FetchType.LAZY, orphanRemoval = true ) var children: MutableList<ChildEntity> = mutableListOf() )
关键说明
- 复合主键
ChildId保证了child表的主键是(parent_id, application),解决了相同application无法属于不同父实体的问题。 orphanRemoval = true会自动删除父实体中不再包含的子实体,配合CascadeType.ALL,插入时会全量保存所有子实体,刚好匹配你“插入全量保存、更新先删再存”的需求。- 移除了原
@JoinColumn中的unique = true配置,该配置会错误限制一个父实体只能有一个子实体,现在通过复合主键实现正确的唯一性约束。 - 使用
MutableList而非List,方便业务层更新子实体列表,确保Hibernate能正确检测到集合变化。
内容的提问来源于stack exchange,提问作者brisssou
相关产品推荐
相关产品推荐

