Doctrine EntityManager未插入ID列问题排查
Doctrine ORM持久化手动赋值UUID实体时ID字段无默认值问题解决
问题现象
采用六边形架构开发,使用Doctrine ORM管理数据实体,MealOptOut实体通过HasUuid trait定义ID字段,并在构造函数中手动生成UUID。调用EntityManager的persist()+flush()方法持久化时触发SQL错误:
An exception occurred while executing a query: SQLSTATE[HY000]: General error: 1364 Field 'id' doesn't have a default value
日志显示Doctrine生成的INSERT语句未包含id列,但实体的ID已确认正确赋值,且同架构下其他实体可正常工作,目前只能通过手动执行SQL临时解决。
问题根源
Doctrine ORM对ID字段默认采用AUTO生成策略,它会默认认为ID由数据库自动生成(比如自增主键),因此在生成INSERT语句时会主动忽略ID字段,即便你已经手动为实体的ID赋值。而其他同架构实体可能已经正确配置了ID生成策略,所以未出现该问题。
解决方案
在HasUuid trait的ID字段上添加#[ORM\GeneratedValue(strategy: 'NONE')]注解,明确告知Doctrine该ID字段由业务代码手动生成,不需要ORM自动处理。
修改后的HasUuid trait代码:
<?php namespace App\Domain\Model; use Doctrine\ORM\Mapping as ORM; trait HasUuid { #[ORM\Id] #[ORM\Column(name: 'id', type: 'string', unique: true)] #[ORM\GeneratedValue(strategy: 'NONE')] // 新增该注解 protected string $id; public function getId(): string { return $this->id; } public function setId(string $id): void { $this->id = $id; } }
额外验证步骤
- 确认数据库表
meal_opt_out的id字段未设置为自增类型(UUID为字符串类型,无需自增) - 恢复Repository中原本的
save方法:
public function save(MealOptOut $mealOptOut): void { $this->getEntityManager()->persist($mealOptOut); $this->getEntityManager()->flush(); }
- 重新执行持久化操作,检查Doctrine生成的INSERT语句是否已包含
id列,确认错误消失。
内容的提问来源于stack exchange,提问作者O'Niel
相关产品推荐
相关产品推荐

