双向OneToMany关联持久化报not-null错误,可否让Hibernate自动填充关联属性
问题根因
你当前使用的是双向@OneToMany关联,mappedBy = "disputeFolder"的配置明确指定了关联关系的维护端是贴文实体的disputeFolder字段。JPA规范中,双向关联只有维护端的字段变化会被同步到数据库,被控端(文件夹实体的postings集合)的变更不会自动维护反向关联,所以仅给文件夹添加贴文时,贴文的disputeFolder仍为空,触发数据库非空约束报错。
解决方案
方案1:保留双向关联,添加封装方法(推荐)
在文件夹实体中添加集合赋值的封装方法,自动维护反向关联,业务层无需感知双向配置:
@Entity @Table(name = "dispute_folder") class DisputeFolderEntity { @Id var id: Long = 0L @OneToMany(mappedBy = "disputeFolder", cascade = [CascadeType.ALL], orphanRemoval = true) lateinit var postings: MutableList<DisputePostingEntity> // 新增封装方法,批量设置贴文时自动关联当前文件夹 fun setPostings(postings: MutableList<DisputePostingEntity>) { this.postings = postings postings.forEach { it.disputeFolder = this } } }
后续业务代码调用folder.setPostings(贴文列表)即可,无需手动给每个贴文设置所属文件夹,适配Spring Batch的写入逻辑。该方案的优势是保留了从贴文查询所属文件夹的能力,符合多数业务场景需求。
方案2:调整关联配置,将维护端改为文件夹侧
如果完全不需要从贴文侧修改所属文件夹,可以直接把关联改为单向,或把贴文侧的关联字段设为只读:
@Entity @Table(name = "dispute_folder") class DisputeFolderEntity { @Id var id: Long = 0L // 去掉mappedBy,添加@JoinColumn指定外键列,关联维护端改为当前实体 @OneToMany(cascade = [CascadeType.ALL], orphanRemoval = true) @JoinColumn(name = "folder", nullable = false) lateinit var postings: MutableList<DisputePostingEntity> } @Entity @Table(name = "dispute_posting") class DisputePostingEntity { @Id var id: Long = 0L // 若不需要从贴文查文件夹可以直接删除该字段,需要保留的话添加insertable、updatable设为只读 @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "folder", insertable = false, updatable = false) lateinit var disputeFolder: DisputeFolderEntity }
改完后你原本仅给文件夹设置贴文列表的代码可以直接正常运行,无需任何额外操作。
内容的提问来源于stack exchange,提问作者Nimelrian
相关产品推荐
相关产品推荐

