2009-08-21 9 views
64

एक लंबा प्रश्न, कृपया मेरे साथ भालू।EntityManager बनाम इंजेक्शन। EntityManagerFactory

हम एक वेब अनुप्रयोग के लिए स्प्रिंग + जेपीए का उपयोग कर रहे हैं। मेरी टीम GenericDAO में EntityManagerFactory इंजेक्शन पर बहस कर रही है (एपीएफएफयूएसई द्वारा प्रदान की गई लाइनों पर जेनेरिक पर आधारित डीएओ, हम किसी कारण से JpaDaosupport का उपयोग नहीं करते हैं) EntityManager इंजेक्शन देने पर। हम "एप्लिकेशन प्रबंधित दृढ़ता" का उपयोग कर रहे हैं।

EntityManagerFactory इंजेक्शन के खिलाफ तर्क यह है कि यह बहुत भारी है और इसलिए इसकी आवश्यकता नहीं है, EntityManager हमें जो चाहिए वह करता है। साथ ही, जैसा कि वसंत प्रत्येक वेब अनुरोध के लिए डीएओ का एक नया उदाहरण बनायेगा (मुझे शक है) EntityManager उदाहरण के रूप में कोई समवर्ती समस्या नहीं होगी, उदाहरण दो धागे से साझा किया जाता है।

ईएफएम इंजेक्शन के लिए तर्क यह है कि कारखाने के लिए एक हैंडल रखने के लिए यह हमेशा अच्छा होता है।

मुझे यकीन नहीं है कि सबसे अच्छा तरीका कौन सा है, क्या कोई मुझे प्रबुद्ध कर सकता है?

+2

मैं आगे समझता हूं कि वसंत EntityManager इंजेक्ट करता है, यह "कंटेनर प्रबंधित दृढ़ता" है और यह भी कि वसंत Entitymanagers थ्रेड सुरक्षित "बनाता है"। एसबी –

उत्तर

49

EntityManagerFactory बनाम EntityManager इंजेक्शन के पेशेवरों और विपक्ष सभी स्प्रिंग दस्तावेज़ here में वर्तनी कर रहे हैं, मुझे यकीन नहीं है कि मैं उस पर सुधार कर सकता हूं।

यह कहकर, आपके प्रश्न में कुछ बिंदु हैं जिन्हें साफ़ किया जाना चाहिए।

... स्प्रिंग हर वेब अनुरोध के लिए एक डीएओ का एक नया उदाहरण बन जाएगा ...

यह सही नहीं है। यदि आपका डीएओ स्प्रिंग बीन है, तो यह एक सिंगलटन है, जब तक कि आप बीन परिभाषा में scope विशेषता के माध्यम से इसे अन्यथा कॉन्फ़िगर नहीं करते। प्रत्येक अनुरोध के लिए डीएओ को तत्काल करना पागल हो जाएगा।

ईएमएफ इंजेक्शन लगाने के लिए तर्क यह है कि अपने से अधिक एक अच्छा अभ्यास सभी अपनी हमेशा एक कारखाने के लिए एक संभाल के लिए अच्छा है।

यह तर्क वास्तव में पानी नहीं पकड़ता है। सामान्य अच्छा अभ्यास कहता है कि किसी ऑब्जेक्ट को न्यूनतम सहयोगियों के साथ इंजेक्शन दिया जाना चाहिए, जिन्हें इसे अपना काम करने की आवश्यकता है।

6

मैंने पाया कि हमारे डीएओ पर @ रिपोजिटरी स्प्रिंग एनोटेशन सेट करना और स्प्रिंग द्वारा प्रबंधित एंटिटी मैनेजर और @PersistenceContext एनोटेशन द्वारा इंजेक्शन करने से सबकुछ ठीक से काम करने का सबसे सुविधाजनक तरीका है। आपको साझा EntityManager और अपवाद अनुवाद की थ्रेड सुरक्षा से लाभ होता है। डिफ़ॉल्ट रूप से, साझा EntityManager लेनदेन का प्रबंधन करेगा यदि आप उदाहरण के लिए प्रबंधक से कई डीएओ जोड़ते हैं। अंत में आप पाएंगे कि आपके डीएओ एनीमिक बन जाएंगे।

23

मैं जो आखिरकार इकट्ठा कर रहा हूं उसे नीचे डाल रहा हूं। अनुभाग "Implementing DAOs based on plain JPA" स्प्रिंग संदर्भ में से:

हालांकि EntityManagerFactory उदाहरणों धागा सुरक्षित हैं, EntityManager उदाहरणों नहीं हैं। इंजेक्शन जेपीए एंटिटी मैनेजर एपीटी मैनेजर की तरह व्यवहार सर्वर के जेएनडीआई पर्यावरण, से जेपीए विनिर्देश द्वारा परिभाषित किया गया है।यह वर्तमान लेनदेन इकाई प्रबंधक, यदि कोई हो, तो सभी कॉल का प्रतिनिधित्व करता है; अन्यथा, यह प्रति ऑपरेशन एक नए बनाए गए EntityManager पर वापस आ जाता है, इसके परिणामस्वरूप उपयोग थ्रेड-सुरक्षित बनाते हैं।

इसका मतलब है जेपीए विनिर्देशों के अनुसार EntityManager उदाहरण थ्रेड सुरक्षित नहीं हैं, लेकिन यदि वसंत उन्हें संभालती है, तो उन्हें थ्रेड सुरक्षित बना दिया जाता है।

यदि आप वसंत का उपयोग कर रहे हैं, तो EntityManagerFactory के बजाय EntityManagers को इंजेक्ट करना बेहतर है।

9

मुझे लगता है कि यह पहले से ही अच्छी तरह से कवर किया गया है, लेकिन केवल कुछ बिंदुओं को मजबूत करने के लिए।

  • डीएओ, अगर स्प्रिंग द्वारा इंजेक्शन, डिफ़ॉल्ट द्वारा एक सिंगलटन है। आपको को प्रत्येक बार एक नया उदाहरण बनाने के लिए प्रोटोटाइप को स्पष्ट रूप से दायरा सेट करना होगा।

  • इकाई चरनी @PersistenceContext द्वारा इंजेक्शन धागा सुरक्षित है।

कहा जा रहा है कि, मेरे बहु-थ्रेडेड एप्लिकेशन में सिंगलटन डीएओ के साथ कुछ समस्याएं थीं। मैंने डीएओ को एक इंस्टेंट बीन बनाने के लिए समाप्त कर दिया और समस्या को हल किया। तो जब दस्तावेज़ एक बात कह सकता है, तो शायद आप अपने आवेदन को पूरी तरह से जांचना चाहते हैं।

का पालन-अप:

मैं मेरी समस्या का हिस्सा लगता है कि मैं का उपयोग कर रहा है

@PersistenceContext(unitName = "unit", 
    type = PersistenceContextType.EXTENDED) 

आप PersistenceContextType.EXTENDED उपयोग करते हैं, मन आप में रखने के लिए, अगर मैं सही ढंग से समझ, लेनदेन को मैन्युअल रूप से बंद करें। अधिक जानकारी के लिए this धागा देखें।

एक और फ़ॉलो-अप:

एक instanced डीएओ का उपयोग करते हुए एक बहुत ही बुरा विचार है। डीएओ के प्रत्येक उदाहरण में अपना स्वयं का दृढ़ता कैश होगा और एक कैश में बदलाव अन्य डीएओ बीन्स द्वारा पहचाना नहीं जाएगा। बुरी सलाह के लिए खेद है।

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