Doctrine实体管理器不插入ID列

问题描述 投票:0回答:1

我有以下型号:

<?php

namespace App\Domain\Model\Meal;

use App\Domain\Model\HasUuid;
use App\Domain\Model\Timestampable;
use App\Domain\Model\User\Child;
use Doctrine\ORM\Mapping as ORM;
use Ramsey\Uuid\Uuid;

#[ORM\Entity]
#[ORM\Table(name: 'meal_opt_out')]
final class MealOptOut
{
    use HasUuid;
    use Timestampable;

    #[ORM\ManyToOne(targetEntity: MealItemSchedule::class)]
    #[ORM\JoinColumn(name: 'meal_item_schedule_id', referencedColumnName: 'id', nullable: false, onDelete: 'CASCADE')]
    private MealItemSchedule $mealItemSchedule;

    #[ORM\ManyToOne(targetEntity: Child::class)]
    #[ORM\JoinColumn(name: 'child_id', referencedColumnName: 'id', nullable: false, onDelete: 'CASCADE')]
    private Child $child;

    public function __construct(
        MealItemSchedule $mealItemSchedule,
        Child $child
    )
    {
        $this->id = Uuid::uuid4()->toString();
        $this->mealItemSchedule = $mealItemSchedule;
        $this->child = $child;
    }
    
    // Getters and setters...
}

具有Uuid特征:

<?php

namespace App\Domain\Model;

use Doctrine\ORM\Mapping as ORM;

trait HasUuid
{
    #[ORM\Id]
    #[ORM\Column(name: 'id', type: 'string', unique: true)]
    protected string $id;

    public function getId(): string
    {
        return $this->id;
    }

    public function setId(string $id): void
    {
        $this->id = $id;
    }
}

我使用的是六角形架构,所以我有一些接口,但最重要的文件是DoctrineMealOptOutRepository:

<?php

namespace App\Infrastructure\Repository\Meal;

use App\Domain\Model\Meal\MealOptOut;
use App\Domain\Repository\Meal\MealOptOutRepositoryInterface;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;

final class DoctrineMealOptOutRepository extends ServiceEntityRepository implements MealOptOutRepositoryInterface
{
    public function __construct(
        private ManagerRegistry $manager,
    )
    {
        parent::__construct($manager, MealOptOut::class);
    }
    
    /*
    public function save(MealOptOut $mealOptOut): void
    {
        $this->getEntityManager()->persist($mealOptOut);
        $this->getEntityManager()->flush();
    }
     */

    public function save(MealOptOut $mealOptOut): void
    {
        $connection = $this->getEntityManager()->getConnection();
        $sql = '
            INSERT INTO meal_opt_out (id, meal_item_schedule_id, child_id, created_at, updated_at)
            VALUES (:id, :meal_item_schedule_id, :child_id, NOW(), NOW())
        ';
        $params = [
            'id' => $mealOptOut->getId(),
            'meal_item_schedule_id' => $mealOptOut->getMealItemSchedule()->getId(),
            'child_id' => $mealOptOut->getChild()->getId(),
        ];

        $connection->executeStatement($sql, $params);
    }
}

MealOptOutRepository接口:

<?php

namespace App\Domain\Repository\Meal;

use App\Domain\Model\Meal\MealOptOut;

interface MealOptOutRepositoryInterface
{
    public function save(MealOptOut $mealOptOut): void;
}

MealOptOutService接口:

<?php

namespace App\Domain\Service\Meal;

use App\Domain\Model\Meal\MealItemSchedule;
use App\Domain\Model\Meal\MealOptOut;
use App\Domain\Model\User\Child;


interface MealOptOutServiceInterface
{
    public function saveMealOptOut(MealOptOut $mealOptOut): ?MealOptOut;
}

MealOptOutService 实施:

<?php

namespace App\Domain\Service\Meal\Impl;

use App\Domain\Model\Meal\MealItemSchedule;
use App\Domain\Model\Meal\MealOptOut;
use App\Domain\Model\User\Child;
use App\Domain\Repository\Meal\MealOptOutRepositoryInterface;
use App\Domain\Service\Meal\MealOptOutServiceInterface;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
use Ramsey\Uuid\Uuid;

final class MealOptOutServiceImplementation extends ServiceEntityRepository implements MealOptOutServiceInterface
{
    public function __construct(
        private MealOptOutRepositoryInterface $mealOptOutRepository,
        private ManagerRegistry $manager,
    )
    {
        parent::__construct($manager, MealOptOut::class);
    }

    public function saveMealOptOut(MealOptOut $mealOptOut): ?MealOptOut
    {
        return $this->mealOptOutRepository->save($mealOptOut);
    }
}

该服务的调用方式如下:

$mealOptOut = new MealOptOut($this->selectedMealItemSchedule, $child);
// $mealOptOut->setId(Uuid::uuid4()->toString());
$this->mealOptOutService->saveMealOptOut($mealOptOut);

问题是当我在DoctrineMealOptOutRepository

中使用这个版本的
save

    public function save(MealOptOut $mealOptOut): void
    {
        $this->getEntityManager()->persist($mealOptOut);
        $this->getEntityManager()->flush();
    }

我收到以下错误:

An exception occurred while executing a query: SQLSTATE[HY000]: General error: 1364 Field 'id' doesn't have a default value
...

at Doctrine\DBAL\Connection->convertExceptionDuringQuery(object(Exception), 'INSERT INTO meal_opt_out (created_at, updated_at, meal_item_schedule_id, child_id) VALUES (?, ?, ?, ?)', array(null, null, 'f8ab33de-ab9d-11ef-bcf3-44da78cb937b', 'a440ab82-573d-4475-a9e3-b5bf839352ed'), array('datetime', 'datetime', 'string', 'string'))

您在日志中看到实体管理器由于某种原因没有插入 id 列。我 100% 确定 id 已设置。我对其他实体使用完全相同的架构和特征,并且它适用于它们。我尝试自动生成 uuid,但这也没有帮助。

我暂时通过手动执行 SQL 来修复它(确实有效,表明 ID 确实设置正确)。

我做错了什么?

php doctrine-orm doctrine
1个回答
-1
投票

您可能缺少GenerateValue行,如下所示:

<?php

namespace App\Domain\Model;

use Doctrine\ORM\Mapping as ORM;

trait HasUuid
{
     #[ORM\Id]
     #[ORM\GeneratedValue(strategy: 'CUSTOM')]
     #[ORM\Column(type: 'uuid', unique: true)]
     #[ORM\CustomIdGenerator(class: UuidGenerator::class)]
     private ?UuidInterface $id = null;
© www.soinside.com 2019 - 2024. All rights reserved.