2012-02-02 103 views
6

我有三个Doctrine实体:Device,它与Device \ Status具有OneToOne关系,而Device \ Status与Device \ Status \ Battery具有OneToOne关系。Doctrine 2多级OneToOne级联

我在相关实体之间设置了{cascade =“persist”},并且从我所读到的内容来看,这应该是所有为自动坚持每个实体所需的全部内容,而无需自己做任何事情代码。

这里是我有什么用的问题:

$device = new \Entities\Device(); 
$device->setId(100); 

$status = $device->getStatus(); 
$status->setIpAddress('192.168.0.1'); 

$battery = $status->getBattery(); 
$battery->setInternalLevel(60); 

$em->persist($device); 
$em->flush(); 

执行此代码后,我收到以下错误:

Entity of type Device\Status\Battery has identity through a foreign entity 
Device\Status, 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 'Device\Status\Battery'. 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. 

我的问题是:什么是正确的方法来设置我的实体以确保它们保持正确的顺序?

为实体的代码可以在这里找到:使用学说2.2沙箱已经进行https://gist.github.com/1753524

所有测试。

+0

我有几乎相同的问题。你必须在每次持续之间调用flush。 – CappY 2012-02-05 18:03:11

+0

@CappY根据Doctrine文档,因为我为每个实体设置了{cascade =“persist”},所以我不需要手动持久化每个实体。此代码*应该*按原样工作。 http://readthedocs.org/docs/doctrine-orm/en/latest/reference/working-with-associations.html#transitive-persistence-cascade-operations – Taeram 2012-02-06 04:10:21

+0

请提供一个[简短,自包含,正确的示例](http ://sscce.org/)。当你尝试将值直接赋值给'protected'属性时,你的代码触发访问冲突,即'$ device-> id = 100' – Phil 2012-02-06 05:08:00

回答

6

我认为@CappY是对的。

问题出在状态实体中。当您执行getBattery()并创建一个新的Battery实例时,它与您调用getBattery()的Status实例相关。

由于该实例尚未存储在数据库中,因此尚未生成id(因为它的注释为@GeneratedValue)。你对cascade persist几乎是正确的。除了它在内存中执行

所以你需要坚持和刷新状态实体之前做getBattery()如果你想使用该实体作为电池中的id。否则你可以简单地为电池添加一个ID字段:)

+0

我刚刚意识到我实际上不得不按下“+50”按钮来奖励赏金,而不只是接受你的答案。所以你去:) – Taeram 2012-02-10 02:12:14

+0

非常感谢:) – jere 2012-02-10 11:24:25

0

你必须在你的关系映射中添加cascade = {“persist”}。您选择的正确答案也是正确的,但是通过该解决方案,如果在插入父数据后出现任何错误,则不会有事务回滚。您必须设置autocommit = false并手动执行提交事务。级联= {“坚持”}你不必。在数据库操作过程中出现任何错误,所有内容都将被回滚。

+0

这就是他正在做的,它没有奏效。你能提供一个完整的例子吗? – cheesemacfly 2013-04-08 19:31:50