क्या जेपीए/हाइबरनेट में डेटाबेस से किसी इकाई को हटाने से सावधानीपूर्वक रोकना संभव है?
हां, जब तक आप EntityManager.remove(entity)
का उपयोग करने से बचें, यह संभव है। यदि आप EntityManager.remove()
का उपयोग करते हैं, तो जेपीए प्रदाता ऑब्जेक्ट को एक संबंधित SQL DELETE कथन का उपयोग करके हटाने के लिए ध्वजांकित करेगा जिसका अर्थ है कि ऑब्जेक्ट को हटाने के लिए ऑब्जेक्ट को ध्वजांकित करने के बाद एक सुरुचिपूर्ण समाधान संभव नहीं होगा।
हाइबरनेट में, आप इसे @SQLDelete
and @Where
annotations का उपयोग करके प्राप्त कर सकते हैं। हालांकि, यह जेपीए के साथ अच्छी तरह से खेल नहीं पाएगा, क्योंकि EntityManager.find()
@Where
एनोटेशन में निर्दिष्ट फ़िल्टर को अनदेखा करने के लिए जाना जाता है।
इसलिए एक जेपीए-एकमात्र समाधान "जीवित" इकाइयों से डेटाबेस में तार्किक रूप से हटाए गए इकाइयों को अलग करने के लिए इकाई वर्गों में एक ध्वज यानी एक कॉलम जोड़ना शामिल होगा। यह सुनिश्चित करने के लिए कि तर्कसंगत हटाए गए इकाइयां परिणाम सेट में उपलब्ध नहीं होंगी, आपको उचित प्रश्न (जेपीक्यूएल और मूल) का उपयोग करने की आवश्यकता होगी। आप @PreUpdate
और @PrePersist
एनोटेशन का उपयोग इकाई जीवन चक्र घटनाओं पर हुक करने के लिए कर सकते हैं ताकि यह सुनिश्चित किया जा सके कि ध्वज जारी रहता है और घटनाओं को अद्यतन करता है। दोबारा, आपको यह सुनिश्चित करने की आवश्यकता होगी कि आप EntityManager.remove
विधि का आह्वान नहीं करेंगे।
मैं जीवन चक्र घटना है कि संस्थाओं को हटाने के लिए शुरू हो रहा है पर हुक करने @PreRemove
एनोटेशन का उपयोग कर सुझाव दिया होता, लेकिन एक इकाई श्रोता का उपयोग कर हटाए जाने को रोकने के लिए नीचे वर्णित कारणों के लिए मुसीबत से भरा है:
- यदि आपको
SQL DELETE
को लॉजिकल अर्थ में होने से रोकने की आवश्यकता है, तो आपको * को फिर से बनाने के लिए उसी लेनदेन में ऑब्जेक्ट को जारी रखना होगा। एकमात्र समस्या यह है कि यह एंटीलिस्टनर में EntityManager
को संदर्भित करने का एक अच्छा डिज़ाइन निर्णय नहीं है, और अनुमान के अनुसार श्रोता में EntityManager.persist
का आह्वान करें। तर्क काफी सरल है - EntityListener में एक अलग EntityManager संदर्भ प्राप्त करने के अंत में समाप्त हो जाएगा और इससे केवल आपके आवेदन में अस्पष्ट और भ्रमित व्यवहार होगा।
- यदि आपको लेनदेन में
SQL DELETE
को होने से रोकने की आवश्यकता है, तो आपको अपने EntityListener में अपवाद फेंकना होगा। यह आम तौर पर लेनदेन को वापस ले जाता है (विशेष रूप से यदि अपवाद एक रनटाइम अपवाद है या एक एप्लिकेशन अपवाद है जिसे रोलबैक का कारण बनता है) घोषित किया जाता है, और कोई लाभ नहीं देता है, क्योंकि पूरे लेनदेन को वापस ले जाया जाएगा।
आप हाइबरनेट के बजाय EclipseLink उपयोग करने का विकल्प है, तो ऐसा लगता है कि एक सुरुचिपूर्ण समाधान संभव है यदि आप एक उपयुक्त DescriptorCustomizer
परिभाषित या AdditionalCriteria
एनोटेशन का उपयोग करके। ये दोनों EntityManager.remove
और EntityManager.find
आमंत्रण के साथ अच्छी तरह से काम करने लगते हैं। हालांकि, आपको अभी भी तार्किक रूप से हटाए गए इकाइयों के लिए अपने जेपीक्यूएल या मूल प्रश्नों को लिखने की आवश्यकता हो सकती है।
* यह JPA Wikibook on the topic of cascading Persist में उल्लिखित है:
अगर आप इसे नष्ट कर दिया है करने के लिए यदि आप तो कहते हैं वस्तु पर जारी रहती है एक वस्तु निकालते हैं तो वह वस्तु को फिर से शुरू होगी, और यह फिर से लगातार बन जाएगा। यह वांछित हो सकता है अगर यह जानबूझकर है, लेकिन जेपीए स्पेक को कैस्केड के लिए इस व्यवहार की भी आवश्यकता होती है। तो यदि आप किसी ऑब्जेक्ट को हटाते हैं, लेकिन एक कैस्केड रिश्ते संबंध से इसका संदर्भ निकालना भूल जाते हैं, तो हटा दिया जाएगा।
स्रोत
2011-07-11 06:31:37
क्या आप जेपीए का उपयोग करके लॉजिकल डिलीशन की नकल करने का प्रयास कर रहे हैं? –
@ विनीत रेनॉल्ड्स - संक्षेप में, हां। मैं चाहता हूं कि रिकॉर्ड चारों ओर रखें क्योंकि ऐप मोबाइल क्लाइंट के साथ समन्वयित करता है, और इसे हटाए जाने वाले ग्राहकों को बताने में सक्षम होना चाहिए। मैं उस समय के साथ-साथ हटाए गए टाइमस्टैम्प के साथ-साथ अलग-अलग तालिका में हटाई गई सभी चीज़ों की आईडी रखकर इस पर काम कर सकता हूं, लेकिन मैं केवल विलोपन व्यवहार को ओवरराइड करने में सक्षम होना पसंद करूंगा ताकि यह सिर्फ उन्हें हटाने के बजाय चीजों को छुपाता है। – aroth