Doctrine 2 多级 OneToOne 级联
我有三个 Doctrine 实体: Device,它与 Device\Status 具有 OneToOne 关系,而 Device\Status 又与 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 沙箱执行。
I have three Doctrine entities: Device, which has a OneToOne relationship with Device\Status, which in turn has a OneToOne relationship with Device\Status\Battery.
I have {cascade="persist"} set between the related entities, and from what I've read, that should be all that is required for Doctrine to automatically persist each of the entities without having to do anything myself in the code.
Here's what I'm having problems with:
$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();
After executing this code, I get the following error:
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.
My question is: what is the correct way to setup my entities to ensure that they're persisted in the correct order?
The code for the entities can be found here: https://gist.github.com/1753524
All tests have been performed using the Doctrine 2.2 sandbox.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我认为@CappY 是对的。
问题出在 Status 实体中。当您执行
getBattery()
并创建新的 Battery 实例时,它与您调用getBattery()
的 Status 实例相关。由于该实例尚未存储在数据库中,因此尚未生成它的 id(因为它被注释为
@GenerateValue
)。你对级联持续的看法几乎是正确的。除此之外它是在内存中执行的。因此,如果您想将该实体用作 Battery 中的 ID,则在执行
getBattery()
之前,您需要保留并刷新 Status 实体。或者你可以简单地为电池添加一个 id 字段:)I think @CappY is right.
The problem is in the Status entity. when you do
getBattery()
and create a new Battery instance, it's related to the Status instance on which you calledgetBattery()
.Since that instance hasn't been stored in the database yet, it's id hasn't been generated (because it's annotated as
@GeneratedValue
). you're almost right about cascade persist. except for that it's performed in memory.So you need to persist and flush Status entity before doing
getBattery()
if you want to use that entity as id in Battery. Or else you could simple add an id field for Battery :)您必须将cascade={"persist"} 添加到关系映射中。您选择的正确答案也是正确的,但是使用该解决方案,如果插入父数据后出现任何问题,将不会出现事务回滚。您必须设置 autocommit=false 并手动执行提交事务。使用cascade={"persist"},你不必这样做。数据库操作过程中出现任何问题,一切都会回滚。
You have to add cascade={"persist"} to your relation mapping. The answer you selected as correct is also correct but with that solution, if anything goes wrong after the parent data is inserted, there will be no transaction rollback. You have to set autocommit=false and perform commit transaction manually. With cascade={"persist"} you dont have to. Anything goes wrong during database action, everything will be rollbacked.