Doctrine 2 多级 OneToOne 级联

发布于 2025-01-02 02:31:22 字数 1233 浏览 1 评论 0原文

我有三个 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

香橙ぽ 2025-01-09 02:31:22

我认为@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 called getBattery().

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 :)

累赘 2025-01-09 02:31:22

您必须将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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文