2012-02-02 15 views
6

Tôi có ba thực thể Doctrine: Thiết bị có mối quan hệ OneToOne với Device \ Status, lần lượt có mối quan hệ OneToOne với Device \ Status \ Battery.Doctrine 2 đa cấp OneToOne Cascade

Tôi có {thác = "tồn tại"} thiết lập giữa các đối tượng liên quan, và từ những gì tôi đã đọc, mà nên là tất cả những gì là cần thiết cho học thuyết để tự động kéo dài mỗi đối tượng mà không cần phải làm bất cứ điều gì bản thân mình trong mật mã.

Dưới đây là những gì tôi đang gặp vấn đề với:

$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(); 

Sau khi thực thi mã này, tôi nhận được lỗi sau:

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. 

Câu hỏi của tôi là: cách chính xác là những gì để thiết lập của tôi thực thể để đảm bảo rằng chúng được duy trì theo đúng thứ tự?

Mã cho các đối tượng có thể được tìm thấy ở đây: https://gist.github.com/1753524

Tất cả các bài kiểm tra đã được thực hiện bằng cách sử dụng sandbox thuyết 2.2.

+0

Tôi đã gặp phải vấn đề tương tự. U phải gọi tuôn ra giữa mỗi tồn tại. – CappY

+0

@CappY Theo tài liệu Doctrine, vì tôi có {cascade = "persist"} được thiết lập cho mỗi thực thể, tôi không cần phải tự tồn tại từng thực thể. Mã này * nên * hoạt động như cũ. http://readthedocs.org/docs/doctrine-orm/en/latest/reference/working-with-associations.html#transitive-persistence-cascade-operations – Taeram

+0

Vui lòng cung cấp [ngắn, tự chứa, ví dụ chính xác] (http : //sscce.org/). Mã của bạn kích hoạt vi phạm truy cập khi cố gán giá trị trực tiếp cho các thuộc tính 'protected', tức là' $ device-> id = 100' – Phil

Trả lời

6

Tôi nghĩ @CappY là đúng.

Sự cố nằm trong thực thể Trạng thái. khi bạn làm getBattery() và tạo một phiên bản Pin mới, nó liên quan đến trường hợp Trạng thái mà bạn gọi là getBattery().

Vì trường hợp đó chưa được lưu trữ trong cơ sở dữ liệu, id của nó chưa được tạo (vì nó được chú thích là @GeneratedValue). bạn gần như đúng về thác vẫn tồn tại. ngoại trừ việc nó được thực hiện trong bộ nhớ.

Vì vậy, bạn cần để duy trì và tuôn ra Thực thể trạng thái trước khi thực hiện getBattery() nếu bạn muốn sử dụng thực thể đó làm id trong Pin. Hoặc bạn có thể đơn giản thêm trường id cho Pin :)

+0

Tôi vừa mới nhận ra rằng tôi thực sự phải nhấn nút "+50" để nhận phần thưởng, và không chỉ chấp nhận câu trả lời của bạn. Vì vậy, có bạn đi :) – Taeram

+0

cảm ơn rất nhiều :) – jere

0

Bạn phải thêm cascade = {"persist"} vào ánh xạ quan hệ của mình. Câu trả lời bạn đã chọn là chính xác cũng đúng nhưng với giải pháp đó, nếu có gì sai sau khi dữ liệu gốc được chèn vào, sẽ không có cuộn ngược giao dịch. Bạn phải đặt autocommit = false và thực hiện giao dịch cam kết theo cách thủ công. Với cascade = {"persist"} bạn không cần phải làm như vậy. Bất cứ điều gì đi sai trong hành động cơ sở dữ liệu, mọi thứ sẽ được khôi phục.

+0

Đó là những gì ông đã làm và nó đã không làm việc. Bạn có thể cung cấp một ví dụ đầy đủ làm việc không? – cheesemacfly