2012-02-02 19 views
6

मेरे पास तीन सिद्धांत इकाइयां हैं: डिवाइस, जिसमें डिवाइस \ स्थिति के साथ OneToOne संबंध है, जिसके बदले डिवाइस \ Status \ बैटरी के साथ एक OneToOne संबंध है।सिद्धांत 2 बहु-स्तर OneToOne कैस्केड

मेरे पास संबंधित संस्थाओं के बीच {cascade = "persist"} सेट है, और जो मैंने पढ़ा है, उससे यह होना चाहिए कि सिद्धांत के लिए यह आवश्यक होना चाहिए कि प्रत्येक इकाई को अपने आप में कुछ भी करने के बिना स्वचालित रूप से बने रहें कोड।

यहाँ है कि मैं क्या साथ समस्या हो रही हूँ:

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. 

मेरा प्रश्न है:

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

इस कोड को क्रियान्वित करने के बाद, मैं निम्नलिखित त्रुटि मिलती है क्या सेटअप करने के लिए सही तरीका क्या है मेरी यह सुनिश्चित करने के लिए संस्थाएं कि वे सही क्रम में बने रहें?

संस्थाओं के लिए कोड यहां पाया जा सकता: https://gist.github.com/1753524

सभी परीक्षणों सिद्धांत 2.2 सैंडबॉक्स का उपयोग किया गया है।

+0

मुझे लगभग एक ही समस्या थी। यू को प्रत्येक persist के बीच फ्लश कॉल करना है। – CappY

+0

@CappY सिद्धांत दस्तावेज़ों के अनुसार, क्योंकि मेरे पास प्रत्येक इकाई के लिए {cascade = "persist"} सेट है, इसलिए मुझे प्रत्येक इकाई को मैन्युअल रूप से जारी रखने की आवश्यकता नहीं है। यह कोड * जैसा * काम करना चाहिए। http://readthedocs.org/docs/doctrine-orm/en/latest/reference/working-with-associations.html#transitive-persistence-cascade-operations – Taeram

+0

कृपया एक [लघु, स्वयं निहित, सही उदाहरण] प्रदान करें (http : //sscce.org/)। आपका कोड सीधे 'संरक्षित' गुणों, यानी '$ डिवाइस-> आईडी = 100' – Phil

उत्तर

6

मुझे लगता है कि @CappY सही है।

समस्या स्थिति इकाई में है। जब आप getBattery() करते हैं और एक नया बैटरी उदाहरण बनाते हैं, तो यह स्थिति उदाहरण से संबंधित है जिस पर आपने getBattery() कहा है।

चूंकि उस डेटाबेस को अभी तक डेटाबेस में संग्रहीत नहीं किया गया है, इसलिए यह आईडी उत्पन्न नहीं हुई है (क्योंकि इसे @GeneratedValue के रूप में एनोटेट किया गया है)। आप कैस्केड के बारे में लगभग सही हैं। इसके अलावा यह मेमोरी में किया गया है।

तो तुम getBattery() करने से पहले जारी रहती है और फ्लश स्थिति संस्था के लिए जरूरत है आप बैटरी में आईडी के रूप में उस संस्था उपयोग करना चाहते हैं । अन्यथा आप बैटरी के लिए एक आईडी फ़ील्ड जोड़ सकते हैं :)

+0

मुझे अभी एहसास हुआ कि मुझे वास्तव में बकाया पुरस्कार देने के लिए "+50" बटन दबा देना था, न केवल आपके उत्तर को स्वीकार करना था। तो आप वहाँ जाते हैं :) – Taeram

+0

बहुत बहुत धन्यवाद :) – jere

0

आपको अपने संबंध मैपिंग में कैस्केड = {"persist"} जोड़ना होगा। आपके द्वारा सही उत्तर के रूप में चयनित उत्तर भी सही है लेकिन उस समाधान के साथ, यदि मूल डेटा डालने के बाद कुछ भी गलत हो जाता है, तो कोई लेनदेन रोलबैक नहीं होगा। आपको autocommit = false सेट करना होगा और मैन्युअल रूप से प्रतिबद्ध लेनदेन करना होगा। कैस्केड = {"persist"} के साथ आपको नहीं करना है। डेटाबेस कार्रवाई के दौरान कुछ भी गलत हो जाता है, सब कुछ रोलबैक हो जाएगा।

+0

यही वह कर रहा था और यह काम नहीं किया। क्या आप एक पूर्ण उदाहरण काम कर सकते हैं? – cheesemacfly

संबंधित मुद्दे