我是Symfony 4和Doctrine的新手,所以也许我对Doctrine ORM的期望太高了,但是我找不到合适的文档来告诉我,这两种方式都让我抓狂!
错误
SQLSTATE[23000]: Integrity constraint violation: 19 UNIQUE constraint failed: skill.id
总结我已经在我的玩家和技能实体之间创建了一个ManyToMany关系。这些实体中的每一个都有自己的ID手动设置,因为它们来自外部API。我正在构建PlayerController中的数据,它抓取第三方应用程序接口以在我的数据库中本地缓存数据。
如果我添加的技能还没有添加到数据库中,那么我编写的代码允许在我的数据库中存储(缓存)第三方数据。但是,如果我尝试添加另一个共享该技能的玩家,整个事务将失败,因为由于唯一id约束,它不能再次添加该技能。我完全明白这一点,但我认为Doctrine ORM足够聪明,可以简单地在连接表中创建条目,而忽略已经存在的技能。
我对Doctrine的期望是不是太高了?如果是这样的话,有没有什么服务或帮助器可以让我在不写一堆代码的情况下摆脱这种情况?
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))
发布于 2018-05-25 19:06:11
尝试下面的注释:
class Player
{
...
/**
* @ORM\ManyToMany(targetEntity="App\Entity\Skill", inversedBy="skill",cascade={"persist"})
*
* @ORM\JoinTable(name="player_skill")
*
*/
private $skill;
...
}
如下所示,使用关系表名
发布于 2018-05-31 18:16:51
你能试试下面的表结构吗?
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;
...
}
https://stackoverflow.com/questions/50518445
复制相似问题