我必须首先确定我是Doctrine的新手,尽管我对SQL和PHP / Symfony 2了解得足够多。
所以,我创建了一个与SQL表关联的IssueType实体:
/**
* IssueType
*
* @ORM\Table()
* @ORM\Entity(repositoryClass="Blog\Bundle\CoreBundle\Entity\IssueTypeRepository")
*/
class IssueType
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="name", type="string", length=255)
*/
private $name;
// Getters, setters...
}
我填充了它,所以表格的内容现在是:
id | name
1 | Bande dessinée
2 | Livre
3 | Film
4 | Disque
现在我有另一个实体Role,它使用复合键,由常规字符串(名称)和外键(来自IssueType的id)组成:
/**
* Role
*
* @ORM\Table()
* @ORM\Entity(repositoryClass="Blog\Bundle\CoreBundle\Entity\RoleRepository")
*/
class Role
{
/**
* @var IssueType
*
* @ORM\ManyToOne(targetEntity="Blog\Bundle\CoreBundle\Entity\IssueType")
* @ORM\JoinColumn(nullable=false)
* @ORM\Id
*/
private $issueType;
/**
* @var string
*
* @ORM\Column(name="name", type="string", length=255)
* @ORM\JoinColumn(nullable=false)
* @ORM\Id
*/
private $name;
// Getters, setters...
}
这两个表都是由数据库中的doctrine正确生成的。然而,虽然它应该是微不足道的,但我不能在我的生活中找到一个正确和成功的持续操作的例子。
我尝试做的是以下内容:
$manager = $this->getDoctrine()->getManager();
$issueType = new IssueType();
$issueType->setId(1);
$role = new Role();
$role->setIssueType($issueType);
$role->setName('Dessinateur');
$manager->persist($role);
$manager->flush();
我因此试图坚持以下内容:
Role: {
IssueType: {id: 1, name: ''},
name: 'Dessinateur',
}
我得到的是这个令人讨厌的例外:
Entity of type Blog\Bundle\CoreBundle\Entity\Role has identity through a foreign entity Blog\Bundle\CoreBundle\Entity\IssueType, however this entity has no identity itself. You have to call EntityManager#persist() on the related entity and make sure that an identifier was generated before trying to persist 'Blog\Bundle\CoreBundle\Entity\Role'. In case of Post Insert ID Generation (such as MySQL Auto-Increment or PostgreSQL SERIAL) this means you have to call EntityManager#flush() between both persist operations.
我理解它希望我首先坚持外国实体,但我不想这样做,因为ID#1的外来问题类型已经存在于数据库中,因此不需要持久化。当我没有在注释中指定任何“级联”属性时,它怎么能问我?
BTY我无论如何都试着按照它的说法去做,并且预计最终会出现重复的输入错误。
那么,我应该怎样做才能让Doctrine明白外国问题类型不应该被保留?
修改
artmees想出了以下解决方案,该方法运行良好:
$manager = $this->getDoctrine()->getManager();
$issueType = $manager->getRepository('BlogCoreBundle:IssueType')->find(1);
$role = new Role();
$role->setIssueType($issueType);
$role->setName('Dessinateur');
$manager->persist($role);
$manager->flush();
然而,这意味着向数据库发出额外请求,如果不使用Doctrine,则可以避免这种请求。由于我已经知道要使用的外部Id,有没有办法直接使用persist(),而不需要实际从数据库中检索完整对象的长度?
答案 0 :(得分:1)
试试这个
$manager = $this->getDoctrine()->getManager();
$issueType = $manager->find('IssueTypeRepository', 1);
$role = new Role();
$role->setIssueType($issueType);
$role->setName('Dessinateur');
$manager->persist($role);
$manager->flush();
答案 1 :(得分:0)
我知道这是一篇旧文章,但是......
只是为了添加artmees答案,如果你知道ID并且你只想插入它,你不需要加载实体,只需使用引用。
$manager = $this->getDoctrine()->getManager();
$issueType = $manager->getReference('BlogCoreBundle:IssueType',1);
$role = new Role();
$role->setIssueType($issueType);
$role->setName('Dessinateur');
$manager->persist($role);
$manager->flush();
这将创建一个具有该ID(1)的代理,这是保存角色实体所需的全部内容。