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

Micronaut R2DBC一对多关联:子表未插入父ID问题

问题:Micronaut + R2DBC 一对多关联保存时外键未自动填充

使用Micronaut结合PostgreSQL构建Person与Address的一对多关联,保存包含Address的Person对象时,两者均成功插入数据库,但Address表的person_id字段为空。

解决方案

问题出在关联关系配置缺失,需调整实体注解建立双向关联,让R2DBC自动维护外键:

1. 调整Person类的关联配置

在Person的addresses字段上添加mappedBy属性,明确关联的反向字段,确保级联配置生效。

2. 为Address类添加双向关联字段

添加指向Person的MANY_TO_ONE关联字段,通过@JoinColumn映射到数据库的person_id列,让框架自动填充外键。

修正后的代码

BaseFields类(无修改)

@Data
@Introspected
@Serdeable
@MappedEntity
public class BaseFields {
    @GeneratedValue
    @Id
    private Long id;
    private String note;
    private String recordType;
}

Person类

@Data
@Introspected
@Serdeable
@MappedEntity
public class Person extends BaseFields{
    private String firstName;
    private String lastName;
    private String phoneNumber;

    @Relation(value = Relation.Kind.ONE_TO_MANY, cascade = Relation.Cascade.ALL, mappedBy = "person")
    private Set<Address> addresses;
}

Address类

@Data
@Introspected
@Serdeable
@MappedEntity
public class Address extends BaseFields {
    private String street;
    private String street2;
    private String suite;
    private String city;
    private String stateProvince;
    private String country;
    private String postalCode;
    private Boolean active;

    @Relation(Relation.Kind.MANY_TO_ONE)
    @JoinColumn(name = "person_id")
    private Person person;

    // 若需保留personId字段,可添加@Transient避免重复映射
    // @Transient
    // public Long getPersonId() {
    //     return person != null ? person.getId() : null;
    // }
}

关键说明

  • 双向关联是R2DBC自动填充外键的必要条件,单方向ONE_TO_MANY无法让框架自动将父实体ID设置到子实体中。
  • @JoinColumn(name = "person_id")必须与数据库外键列名完全匹配。
  • 级联配置cascade = Relation.Cascade.ALL确保保存Person时自动保存关联的Address。

验证结果

修改后重新发送请求,数据库中Address记录的person_id会被正确填充为对应的Person ID,返回的JSON结果也会包含完整关联数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 04:06:19