2012-06-27 16 views
5

जब भी मैं किसी भी इकाई को जारी रखना चाहता हूं तो निम्नलिखित कोड निष्पादित हो जाता है। चीजें ठीक काम कर रही हैं लेकिन मुझे यह समझने में असफल रहा कि यह कैसे काम करता है!जेपीए लेनदेन कैसे काम करता है

EntityManager em = getEntityManager(); 
EntityTransaction userTransaction = em.getTransaction(); 
userTransaction.begin(); 
em.persist(ent); 
userTransaction.commit(); 

उपरोक्त EntityManager पूरे एप्लिकेशन द्वारा साझा किया गया एक उदाहरण है। लेनदेन शुरू करने के बाद; मैं सिर्फ em.persist (इकाई) कहता हूं .. हाइबरनेट कैसे जानता है कि यह किस लेनदेन से संबंधित है!

मान लीजिए कि मेरे आवेदन पर 10 समवर्ती उपयोगकर्ता हैं और उपरोक्त कोड निष्पादित सभी 10 धागे हैं। तो 10 स्वतंत्र लेनदेन बनाए और प्रतिबद्ध किए जा रहे हैं। लेकिन सभी 10 अलग-अलग संस्थाएं मैं उन्हें अपने संबंधित लेनदेन से जोड़ नहीं रहा हूं; तो जेपीए इसे कैसे काम करने में सक्षम है!

उत्तरों के आधार पर; हमारे पास नीचे है; क्या हम कह रहे हैं कि हमारे पास प्रति थ्रेड एंटिटी मैनेजर इंस्टेंस होना चाहिए? क्या यह सर्वर पर एक हत्या नहीं होगी! क्या हमें इन उदाहरणों को पूल करना चाहिए? क्या यह फिर से कनेक्शन पूलिंग को लागू करने के बराबर नहीं होगा?

+2

आपका क्या मतलब है "कौन सा लेनदेन"? एक ईएम में किसी भी समय एक एकल (स्थानीय) लेनदेन होता है; इसमें एकाधिक नहीं है। एकाधिक धागे में एक एकल ईएम साझा करना समस्याओं के लिए एक नुस्खा है, क्योंकि यह थ्रेड-सुरक्षित होने की गारंटी नहीं है। – DataNucleus

+0

http://docs.jboss.org/hibernate/orm/4.0/hem/en-US/html/transactions.html एक EntityManagerFactory एक महंगी-टू-बिल्ड, थ्रेडसेफ ऑब्जेक्ट है जो सभी एप्लिकेशन थ्रेड द्वारा साझा किया जाना है। यह आमतौर पर एप्लिकेशन स्टार्टअप पर एक बार बनाया जाता है। एक EntityManager एक सस्ती, गैर-थ्रेडसेफ ऑब्जेक्ट है जिसे एक ही व्यवसाय प्रक्रिया के लिए, काम की एक इकाई के लिए, और फिर – Deepak

+0

को छोड़कर आगे पढ़ने पर उपयोग किया जाना चाहिए; मैं समझता हूं कि EntityManager का निर्माण हल्का वजन है लेकिन अभी भी बहुत हल्का वजन नहीं है कि प्रत्येक छोटे डीबी ऑपरेशन के लिए हम इसे बनाते हैं। सुझाए गए समाधान ईएम प्रति अनुरोध बनाने के लिए है। तो, ऐसा लगता है कि यह थ्रेडलोकल स्तर पर होना चाहिए। – Deepak

उत्तर

4

यह काम करता है क्योंकि आप भाग्यशाली हैं। भाग्यशाली पर्याप्त मतलब है कि प्रतिबद्धता और शुरुआत सही क्रम में बुलाया जाता है - गलती से।

आप एकाधिक धागे से इकाई प्रबंधक के एकल उदाहरण का उपयोग करते हैं। ऐसा करना गलत बात है, क्योंकि यह थ्रेड सुरक्षित होने की गारंटी नहीं है। EntityTransaction के माध्यम से संसाधन स्तर लेनदेन तक पहुंच थ्रेड के लिए नहीं, इकाई प्रबंधक उदाहरण के लिए बाध्य है।

तो परिणाम यह है कि आप एक ही EntityTransaction साझा कर रहे हैं और इसे कई लेनदेन के लिए सौभाग्य से क्रमशः उपयोग कर रहे हैं। इसे कई लेन-देन को समाप्त करने और समाप्त करने के लिए क्रमशः इसका उपयोग करना ठीक है, लेकिन कई धागे से इसका उपयोग करना नहीं है।

हाइबरनेट (4.1.4) संदर्भ में AbstractEntityManageImpl क्लास में tx उदाहरण फ़ील्ड में संग्रहीत किया जाता है, लेकिन यह केवल कार्यान्वयन विवरण है।

+0

क्या हम कह रहे हैं कि हमारे पास प्रति थ्रेड EntityManager इंस्टेंस होना चाहिए? क्या यह सर्वर पर एक हत्या नहीं होगी! क्या हमें इन उदाहरणों को पूल करना चाहिए? क्या यह फिर से कनेक्शन पूलिंग को लागू करने के बराबर नहीं होगा? – Deepak

+2

EntityManager बनाने के लिए काफी हल्का ऑब्जेक्ट है, EntityManagerFactory भारी वजन है। पूल इकाई प्रबंधकों को शुरू करने का कोई कारण नहीं है। –

+0

मैं समझता हूं कि EntityManager थ्रेडसेफ नहीं है जिसके लिए हमें नई ऑब्जेक्ट्स बनाना चाहिए। लेकिन क्या हमें चुनिंदा क्वेरी के लिए भी नई इकाई प्रबंधक बनाने की जरूरत है (जिसके लिए हम कोई लेनदेन शुरू नहीं करते हैं) .. क्या यह अधिक नहीं होगा? – Deepak

1

लेनदेन किसी थ्रेडलोकल चर का उपयोग करके किसी भी तरह से मौजूदा धागे से जुड़ा हुआ है। यह काफी महत्वपूर्ण है अपने
इसके अलावा समझने के लिए, कंटेनर से प्रबंधित लेनदेन और सेम कामयाब लेनदेन के बारे में पढ़ा -

+1

तो डिजाइन के ऊपर दोषपूर्ण है या नहीं! मैं अभी भी उलझन में हूँ! – Deepak

+0

यह सब इस बात पर निर्भर करता है कि आप EntityManager का उदाहरण कैसे प्राप्त करते हैं। यदि इसे ईजेबी में या स्प्रिंग बीन्स में इंजेक्शन दिया गया है (जैसा कि स्प्रिंग प्रलेखन में बताया गया है), EntityManager वास्तव में वास्तविक EntityManager कार्यान्वयन के लिए प्रॉक्सी है। यदि नहीं, तो मिक्को मौनू का जवाब देखें। –

+1

मैं समझता हूं कि EntityManager थ्रेडसेफ नहीं है जिसके लिए हमें नई ऑब्जेक्ट्स बनाना चाहिए। लेकिन क्या हमें चुनिंदा क्वेरी के लिए भी नई इकाई प्रबंधक बनाने की जरूरत है (जिसके लिए हम कोई लेनदेन शुरू नहीं करते हैं) .. क्या यह अधिक नहीं होगा? – Deepak

0

मैं तुम्हें समझ कैसे काम करता है JTA हाइबरनेट की परवाह किए बिना सलाह देते हैं।
यदि आप एक कंटेनर-प्रबंधित लेनदेन में काम कर रहे हैं, तो आप उस बीन के लिए निर्दिष्ट कर सकते हैं, जिसे आप एंटाइटी मैनेजर इंजेक्शन कर रहे हैं, लेनदेन के दायरे में क्या है -
उदाहरण के लिए - यदि दायरा आवश्यक है, तो इसका मतलब है कि यदि कोई और बीन इस बीन को कॉल करता है, न कि लेनदेन के संदर्भ में, एक नया लेनदेन खुला होगा। यदि कोई लेनदेन पहले से मौजूद है, तो आप उसी लेनदेन का उपयोग करेंगे। यह समझना महत्वपूर्ण है, क्योंकि लेनदेन आपके सिस्टम में एक महंगा संसाधन है।

लेनदेन वस्तु ThreadLocal साथ जुड़ा हुआ है, फिर भी, एक और धागा एक निलंबित लेन-देन को फिर से शुरू कर सकते हैं, अपने TransactionManager के कार्यान्वयन पर निर्भर करता है (मैं बात कर रहा हूँ के बारे में JBossTransactionManager)

+1

वह स्थानीय लेनदेन का उपयोग कर रहा है, जैसा कि em.getTransaction() पर कॉल द्वारा दिखाया गया है। और उस मामले में प्रति ईएम केवल 1 लेनदेन है, और उसका डिजाइन त्रुटिपूर्ण है। – DataNucleus

5

यह लेनदेन के लिए ThreadLocal चर का उपयोग कर रहा है।

UserTransaction के लिए भी दस्तावेज़ देखें:

शुरू()
एक नया लेनदेन बनाएँ और वर्तमान धागा के साथ संबद्ध।

आपको EntityManager साझा नहीं करना चाहिए, हालांकि यह थ्रेड-सुरक्षित होने की गारंटी नहीं है।

लेकिन यदि आप एक EJB में यह इंजेक्शन लगाने रहे हैं, आप धागे की सुरक्षा के बारे में चिंता करने की ज़रूरत नहीं है: http://www.adam-bien.com/roller/abien/entry/is_in_an_ejb_injected

आप इसकी सुई देने वसंत का उपयोग कर रहे हैं, तो आप एक धागा सुरक्षित प्रॉक्सी मिल जाएगा: http://static.springsource.org/spring/docs/3.1.1.RELEASE/spring-framework-reference/html/orm.html#orm-jpa-straight

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

+1

यह कम से कम हाइबरनेट के ताजा कार्यान्वयन के लिए सच नहीं है।यह ऑब्जेक्ट में थ्रेडलोकल का उपयोग क्यों करेगा जो केवल एक धागे से उपयोग किया जाने वाला है? –

+1

ऐसा लगता है कि आप इसका उपयोग कहां करते हैं: http://stackoverflow.com/questions/8603478/does-jboss-handle-managed-entity-manager-concurrency-issues-for-me – Sandro

+0

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

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