Doctrine orm 规则ORM无法持久化多个对象的一侧(SQLSTATE[23000]:唯一约束冲突)
我是Symfony 4和条令的新手,所以也许我对条令ORM的期望太高了,但事实上我找不到合适的文档来告诉我这两种方式都让我发疯了 错误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刮取到数
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。尝试过了,没有什么区别。谢谢你的建议。你能分享一下吗您正在使用的中间表结构?我会将其添加到原始问题中(抱歉延迟)