【问题标题】:Doctrine 2 multi-level OneToOne CascadeDoctrine 2 多级 OneToOne 级联
【发布时间】:2012-02-25 09:31:06
【问题描述】:

我有三个 Doctrine 实体:Device,它与 Device\Status 具有 OneToOne 关系,它又与 Device\Status\Battery 具有 OneToOne 关系。

我在相关实体之间设置了 {cascade="persist"},根据我的阅读,这应该是 Doctrine 自动持久化每个实体所需的全部内容,而无需我自己在代码。

这是我遇到的问题:

$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.

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

实体的代码可以在这里找到:https://gist.github.com/1753524

所有测试均使用 Doctrine 2.2 沙箱进行。

【问题讨论】:

  • 我遇到了几乎同样的问题。你必须在每个持久化之间调用flush。
  • @CappY 根据 Doctrine 文档,由于我为每个实体设置了 {cascade="persist"},我不需要手动持久化每个实体。此代码应该按原样工作。 readthedocs.org/docs/doctrine-orm/en/latest/reference/…
  • 请提供short, self contained, correct example。您的代码在尝试将值直接分配给protected 属性时触发访问冲突,即$device->id = 100
  • 如果在设置了每个属性之后你也设置了反面呢?像这样:在$status->device = $device; 之后执行$device->status = $status;,然后在$battery->status = $status; 之后执行$status->battery = $battery;
  • @Phil 完成,谢谢提醒。

标签: php orm doctrine mapping doctrine-orm


【解决方案1】:

我认为@CappY 是对的。

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

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

因此,如果您想将该实体用作 Battery 中的 id,那么您需要在执行 getBattery() 之前保留并刷新 Status 实体。或者你可以简单地为电池添加一个 id 字段:)

【讨论】:

  • 我刚刚意识到我实际上必须按下“+50”按钮来奖励赏金,而不仅仅是接受你的回答。所以你去:)
【解决方案2】:

您必须将 cascade={"persist"} 添加到您的关系映射中。您选择的正确答案也是正确的,但是使用该解决方案,如果在插入父数据后出现任何问题,则不会有事务回滚。您必须设置 autocommit=false 并手动执行提交事务。使用 cascade={"persist"} 您不必这样做。数据库操作期间出现任何问题,所有内容都将回滚。

【讨论】:

  • 这就是他正在做的,但没有奏效。你能提供一个完整的例子吗?
猜你喜欢
  • 2011-06-29
  • 1970-01-01
  • 1970-01-01
  • 2016-12-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-05
  • 1970-01-01
相关资源
最近更新 更多