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

Doctrine复合主键单向一对一关联保存时project_id被覆盖为null问题

这是映射配置错误,不属于Doctrine的bug。

问题原因

你的Passenger实体中project_id字段被同时映射到了两个属性:

  1. 作为复合主键的一部分,映射到$projectId属性,你可以通过setProjectId手动赋值
  2. 作为和Ticket关联的外键的一部分,映射到$ticket属性的关联配置
    当你没有给$ticket赋值时,Doctrine的关联处理逻辑会自动将关联对应的外键字段project_id设为null,直接覆盖了你之前手动设置的projectId值,最终生成的SQL就会出现project_id为null的情况,触发非空约束报错。
    而你设置了$ticket关联对象时,Doctrine会自动从Ticket对象中读取projectId的值填充到project_id外键字段,刚好满足非空要求,所以不会报错。

修复方案

修改Passenger实体中关联部分的注解,给对应project_id的JoinColumn增加insertable: false和updatable: false配置,禁止Doctrine通过关联逻辑操作这个字段,字段值完全由实体本身的$projectId属性控制:

#[OneToOne(targetEntity: "Ticket", cascade: ["persist"])]
#[JoinColumn(name: "ticket_id", referencedColumnName: "id", nullable: true)]
#[JoinColumn(name: "project_id", referencedColumnName: "project_id", insertable: false, updatable: false)]
private ?Ticket $ticket;

如果你的业务逻辑要求Passenger的project_id必须和关联Ticket的project_id保持一致,可以在setTicket方法中补充同步逻辑:

public function setTicket(?Ticket $ticket): void
{
    $this->ticket = $ticket;
    if ($ticket !== null) {
        $this->setProjectId($ticket->getProjectId());
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 08:36:05