रोलबैक के बाद संस्थाओं को अद्यतन करने के साथ कैसे व्यवहार करें? ("EntityManager बंद है")

मैं एक लेनदेन के भीतर कुछ प्रसंस्करण करने की कोशिश कर रहा हूं और संभावित विफलता के बारे में जानकारी सहेज रहा हूं, इस तरह:

$conn->beginTransaction();
try
{
    $report = $reportRepository->find($id);
    $user = $report->getUser();

    $specification = new Specification();
    $entityManager->persist($specification);

    throw new ProcessingWentWrongException();

    $entityManager->flush();
    $conn->commit();
}
catch(ProcessingWentWrongException $e)
{
    $conn->rollback();

   //Store error info:
    $report->setState('error');
    $entityManager->persist($report);
    $entityManager->flush();//all hell breaks loose in here
}

यह वास्तव में एक आम पैटर्न की तरह दिखता है, लेकिन सिद्धांत इसे करने में वाकई मुश्किल बनाता है:

  1. flush in the catch{} section will try to persist both the $report and $specification object which obviously is wrong, so I could clear the entityManager, but then...

  2. If I clear the entityManager, $report is no longer managed by it, so I need to call $em->merge($report) to make it managed again. Obviously $user will stay unmanaged so doctrine will either perform an insert or complain about persist cascade. So I can either merge() the whole graph (which sucks) or close the entityManager, but then...

  3. If I close the entityManager I can only re-retrieve the report instance via $repo->find($id); - but I don't want to do that, it's stupid.

क्या मैं कुछ भूल गया? उपरोक्त परिणाम प्राप्त करने के लिए कोई और तरीका है? मुझे लगता है जैसे सिद्धांत आसान चीजें कठिन बनाता है।

7
एक असली समाधान नहीं है, लेकिन मुझे लगता है कि प्रत्येक persist() के बाद flush() को कॉल करने में मदद मिलेगी, कम से कम जब तक persist() द्वारा फेंक दिया गया कोई अपवाद नहीं है
जोड़ा लेखक siergiej, स्रोत

2 उत्तर

संक्षिप्त जवाब

दो इकाई प्रबंधकों का प्रयोग करें। एक संभावित असुरक्षित संचालन और दूसरे पर लॉगिंग/रिपोर्टिंग के लिए एक।

लंबा जवाब

आम तौर पर, आप यह सुनिश्चित नहीं कर सकते कि त्रुटियां नहीं होती हैं (डेटाबेस में फ्लश करने से पहले कुछ त्रुटियां नहीं होती हैं)। और एक बार ऐसा होने पर, इकाई के लिए इकाई बंद कर दिया जाता है।

यहां मैं क्या करता हूं (config.yml से अंश):

doctrine:
    orm:
        default_entity_manager: 'default'
        entity_managers:
            default:
                mappings: { ... }
            logging:
                mappings: { ... }

सामान्य परिचालनों के लिए, मैं डिफ़ॉल्ट इकाई प्रबंधक का उपयोग करता हूं, जिसके लिए आपके कोड में कोई बदलाव की आवश्यकता नहीं होती है।

मेटा-ऑपरेशंस के लिए (जैसे बैच किए गए आयात या कुछ समान की प्रगति या परिणाम लॉगिंग करना), मैं स्पष्ट रूप से 'लॉगिंग' प्रबंधक लाता हूं और लॉगिंग/रिपोर्ट इकाइयों को बनाने/अपडेट करने के लिए इसका उपयोग करता हूं (और केवल उन लोगों के लिए)।

4
जोड़ा
मैं ऑब्जेक्ट को पुन: पुनर्प्राप्त करने के लिए गया था क्योंकि किसी अन्य इकाई प्रबंधक का उपयोग करने से अब भी अप्रबंधित संबंध ग्राफ की समस्या आती है, लेकिन मुझे लगता है कि मेरा समाधान बेकार है, कोई अन्य विचार? :)
जोड़ा लेखक siergiej, स्रोत
आह, मैं देखता हूं कि मैं आपके प्रश्न को पूरी तरह समझ नहीं पाया। यदि आपकी समस्या यह है कि आप बहुत सारी संस्थाओं को साफ़/अलग कर रहे हैं, तो ऐसी रणनीति बनाने के बारे में जो केवल समस्याग्रस्त इकाई (-ies) को अलग करता है (जिसे आप अपवाद से जोड़ सकते हैं ताकि उन्हें कैच ब्लॉक में संभाला जा सके)? या - आप उन वस्तुओं को कैसे पहचानते हैं जिन्हें आप पहली जगह में अलग करना चाहते हैं?
जोड़ा लेखक Martin Lie, स्रोत

इस विशेष उदाहरण में आप रिपोर्ट पर विनिर्देश जोड़ रहे हैं। तो क्या आप यह कर सकते हैं?

$entityManager->clear("Your\Bundle\Entity\Specification");

और फिर जैसा आपने प्रस्तावित किया है:

// Store error info:
$report->setState('error');
$entityManager->persist($report);
$entityManager->flush();//all hell breaks loose in here

साथ ही, मुझे लगता है कि असाइन आईडी के साथ ऑब्जेक्ट पर persist करना अमान्य है। ( $ report ऑब्जेक्ट catch शाखा में)

1
जोड़ा
कॉलिंग $ entityManager-> स्पष्ट() बिना तर्क के सभी इकाइयों को अलग कर देगा। स्रोत विवरण के लिए।
जोड़ा लेखक Lg102, स्रोत
धन्यवाद! यह सिर्फ एक सरलीकृत उदाहरण है, मेरे पास 30 अलग-अलग संबंध परिभाषित हैं, उनमें से प्रत्येक के अपने संबंध हैं - इसलिए मैं अधिक सामान्य समाधान की तलाश में हूं।
जोड़ा लेखक siergiej, स्रोत
एह और <कोड> जारी रखें असाइन किए गए आईडी वाले किसी ऑब्जेक्ट पर कम से कम v2.3.4 में मान्य है - सिद्धांत एंटीटी मैनेजर द्वारा प्रबंधित किया गया है या नहीं, इस पर निर्भर करता है कि सिद्धांत अद्यतन या सम्मिलित करेगा या नहीं
जोड़ा लेखक siergiej, स्रोत
धन्यवाद, उसे नहीं पता था। मैं कुछ महीने पहले खुद को अधिक सामान्य समाधान की खोज कर रहा हूं - इकाइयों को सामान्य करने में array में समाप्त हो गया और इसे MongoDB सर्वर में पंप कर रहा था। पूरा विचार यह था कि क्या बदल गया है और यह किसने किया था। अब, मैंने फ्लश असफलताओं को कवर करने का प्रयास नहीं किया ...
जोड़ा लेखक Jovan Perovic, स्रोत