Doctrine orm 规则ORM无法持久化多个对象的一侧(SQLSTATE[23000]:唯一约束冲突)

Doctrine orm 规则ORM无法持久化多个对象的一侧(SQLSTATE[23000]:唯一约束冲突),doctrine-orm,orm,doctrine,symfony4,Doctrine Orm,Orm,Doctrine,Symfony4,我是Symfony 4和条令的新手,所以也许我对条令ORM的期望太高了,但事实上我找不到合适的文档来告诉我这两种方式都让我发疯了 错误 SQLSTATE[23000]: Integrity constraint violation: 19 UNIQUE constraint failed: skill.id 摘要 我已经在我的玩家和技能实体之间建立了很多关系。这些实体中的每一个都手动设置了其ID,因为它们来自外部API。我正在PlayerController中构建数据,它将第三方API刮取到数

我是Symfony 4和条令的新手,所以也许我对条令ORM的期望太高了,但事实上我找不到合适的文档来告诉我这两种方式都让我发疯了

错误

SQLSTATE[23000]: Integrity constraint violation: 19 UNIQUE constraint failed: skill.id
摘要 我已经在我的玩家和技能实体之间建立了很多关系。这些实体中的每一个都手动设置了其ID,因为它们来自外部API。我正在PlayerController中构建数据,它将第三方API刮取到数据库中的本地缓存数据

如果我要添加的技能尚未添加到数据库中,我编写的代码允许在数据库中存储(缓存)第三方数据。但是,如果我尝试添加另一个共享该技能的玩家,整个事务将失败,因为由于唯一id限制,它无法再次添加该技能。我完全明白这一点,但我认为ORM足够聪明,可以简单地在连接表中创建条目,而忽略已经存在的技能

我是否期望太多的原则,如果是这样,是否有任何服务或帮助,让我摆脱这种情况,而不写一堆代码

PlayerController执行此操作以保存数据:

private function persistPlayer($data){

    $player = new Player($data);  //Player __construct entity extracts + assigns data

    foreach ($data->skills as $rawSkill) {
                $skill = new Skill($rawSkill);
                $player->addSkill($skill);
            }
    }

    $this->entityManager->persist($player);

    try {

        $this->entityManager->flush();

    } catch (\Exception $e) {

        error_log($e->getMessage());

    }
    return $player;
}
我的实体注释如下所示(并且是使用
bin/console make:entity
命令创建的:

class Player
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\ManyToMany(targetEntity="App\Entity\Skill", inversedBy="skill",cascade={"persist"})
     */
    private $skill;




public function __construct($data)
{
    $this->ability = new ArrayCollection();
    $this->setId($data->id);
}


   public function addSkill(Skill $skill): self
    {
        if (!$this->skill->contains($skill)) {
            $this->skill[] = $skill;
        }

        return $this;
    }

    //.... more code

}
和我的技能实体:

/**
 * @ORM\Entity(repositoryClass="App\Repository\SkillRepository")
 */
class Skill
{
    /**
     * @var integer $id
     * @ORM\Column(name="id", type="integer", nullable=false)
     * @ORM\Id
     */
    private $id;


    /**
     * @ORM\ManyToMany(targetEntity="App\Entity\Player", mappedBy="skill" ,cascade={"persist"})
     */
    private $skill;


    public function __construct($data)
    {
        $this->ability = new ArrayCollection();

         $this->setId($data->id);

    }

    public function setId($id)
    {
        return $this->id = $id;
    }


//...more code


}
我的连接表是使用以下语法创建的:

CREATE TABLE player_skill (player_id INTEGER NOT NULL, skill_id 
INTEGER NOT NULL, PRIMARY KEY(player_id, skill_id))
请尝试以下注释:

class Player
{

...

/**
 * @ORM\ManyToMany(targetEntity="App\Entity\Skill", inversedBy="skill",cascade={"persist"})
 *
 * @ORM\JoinTable(name="player_skill")
 *
 */
private $skill;

...

}

这样,使用关系表名

可以尝试以下表结构吗

CREATE TABLE `player_skill` (`id` int(10) unsigned NOT NULL AUTO_INCREMENT, `user_id` int(10) unsigned NOT NULL, `role_id` int(10) unsigned NOT NULL, PRIMARY KEY (`id`), KEY `playerSkill_skillId_idx` (`skill_id`), KEY `playerSkill_playerId_idx` (`player_id`), CONSTRAINT `playerSkill_skillId_idx` FOREIGN KEY (`skill_id`) REFERENCES `skill` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `playerSkill_playerId_idx` FOREIGN KEY (`player_id`) REFERENCES `player` (`id`) ON DELETE CASCADE ON UPDATE CASCADE) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
并跟随注释

class Player
{

...

/**
 * @ORM\ManyToMany(targetEntity="App\Entity\Skill", 
inversedBy="skill",cascade={"persist"})
 *
 * @ORM\JoinTable(name="player_skill")
 *
 */
private $skill;

...

}

你能同时添加玩家和技能构造器代码吗?它们都包含数组集合。你能在那里设置技能id吗?你能添加相关代码吗,也许会有帮助?我已经添加了两个构造器。链接表中的列名应该是,玩家id,技能id。尝试过了,没有什么区别。谢谢你的建议。你能分享一下吗您正在使用的中间表结构?我会将其添加到原始问题中(抱歉延迟)