कुछ प्रयोग करने के बाद, मैंने पाया है कि वास्तव में दो स्थिरता इकाइयां हैं जो एक कंटेनर-प्रबंधित लेनदेन के भीतर गैर-एक्सए संसाधनों का उपयोग करती हैं। हालांकि, यह कार्यान्वयन-निर्भर हो सकता है। टीएल; नीचे डीआर।
यदि किसी एक से अधिक संसाधन लेन-देन में भाग लेते हैं तो जेटीए को एक्सए संसाधनों की आवश्यकता होनी चाहिए। यह वितरित लेनदेन की अनुमति के उद्देश्य से एक्स/ओपन एक्सए का उपयोग करता है, उदाहरण के लिए एकाधिक डेटाबेस, या डेटाबेस और जेएमएस कतार में। स्पष्ट रूप से कुछ अनुकूलन है (यह ग्लासफ़िश-विशिष्ट हो सकता है, मुझे यकीन नहीं है) जो अंतिम प्रतिभागी को गैर-एक्सए होने की अनुमति देता है। मेरे उपयोग-मामले में, हालांकि, दोनों दृढ़ता इकाइयां एक ही डेटाबेस के लिए हैं (लेकिन कुछ संभावित ओवरलैप के साथ तालिकाओं का एक अलग सेट) और दोनों गैर-एक्सए हैं। इसका मतलब है कि जब हम दूसरा संसाधन XA का समर्थन नहीं करते हैं तो हम एक अपवाद को फेंकने की उम्मीद करेंगे।
मान लीजिए यह हमारे persistence.xml
है
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="playground" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>jdbc/playground</jta-data-source>
<properties>
<property name="hibernate.dialect" value="be.dkv.hibernate.SQLServer2012Dialect" />
<property name="hibernate.hbm2ddl.auto" value="update" />
<property name="hibernate.show_sql" value="true" />
</properties>
</persistence-unit>
<persistence-unit name="playground-copy" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>jdbc/playground</jta-data-source>
<mapping-file>META-INF/orm-playground-copy.xml</mapping-file>
<properties>
<property name="hibernate.dialect" value="be.dkv.hibernate.SQLServer2012Dialect" />
<property name="hibernate.hbm2ddl.auto" value="update" />
<property name="hibernate.show_sql" value="true" />
</properties>
</persistence-unit>
</persistence>
दो हठ इकाइयों, नाम playground
के साथ एक, नाम playground-copy
के साथ अन्य रहे हैं। उत्तरार्द्ध में एक ओआरएम मैपिंग फ़ाइल है लेकिन यह बिंदु के अलावा थोड़ा सा है। महत्वपूर्ण यह है कि दोनों के पास <jta-data-source>
निर्दिष्ट है।
एप्लिकेशन सर्वर (इस मामले में ग्लासफ़िश) में, हमारे पास एक जेडीबीसी कनेक्शन पूल होगा, जिसमें एक जेडीबीसी संसाधन playground
है जो इस पूल का उपयोग करता है।
अब दो हठ संदर्भों एक EJB में इंजेक्ट किया जाता है, और एक विधि कहा जाता है कि एक कंटेनर से प्रबंधित लेन-देन के भीतर माना जाता है, आप चीजों को इस तरह देखने के लिए उम्मीद थी, तो।
दोनों दृढ़ता संदर्भों में एक ही डेटा स्रोत का उपयोग, लेकिन न तो लेन-देन प्रबंधक और न ही जेपीए परत वास्तव में उस के बारे में ज्यादा ध्यान देना चाहिए। आखिरकार, उनके पास अलग-अलग डेटा स्रोत हो सकते हैं। चूंकि डेटा स्रोत को किसी भी कनेक्शन पूल द्वारा समर्थित किया जाता है, इसलिए आप दोनों इकाइयों को अपना कनेक्शन प्राप्त करने की अपेक्षा करेंगे। एक्सए कार्य को लेनदेन के तरीके से संचालित करने की अनुमति देगा, क्योंकि एक्सए-सक्षम संसाधन 2-चरण प्रतिबद्धता लागू करेंगे।
हालांकि, गैर-एक्सए कार्यान्वयन (और कुछ वास्तविक दृढ़ता कार्य करने वाले) के साथ कनेक्शन पूल को इंगित करने वाले डेटा स्रोत के साथ उपरोक्त प्रयास करते समय, कोई अपवाद नहीं था और सबकुछ ठीक काम करता था! एमएसएसक्यूएल सर्वर में एक्सए समर्थन भी अक्षम कर दिया गया था और एक्सए चालक का उपयोग करने का प्रयास करने के परिणामस्वरूप त्रुटि हो गई थी, इसलिए ऐसा नहीं है कि मैं गलती से बिना एक्सए के एक्सए का उपयोग कर रहा था।
डीबगर के साथ कोड में जाकर पता चला कि दोनों दृढ़ता संदर्भ, अलग-अलग इकाई प्रबंधकों (जैसा कि उन्हें करना चाहिए) वास्तव में एक ही कनेक्शन का उपयोग करते थे। कुछ और खुदाई से पता चला कि कनेक्शन को एक्सए लेनदेन में नहीं रखा गया था, और जेडीबीसी स्तर पर एक ही लेनदेन पहचानकर्ता था। तो स्थिति यह बन गया:
मैं केवल यह मान सकते हैं जेपीए प्रदाता एक ही कनेक्शन का उपयोग करने के कई इकाइयों एक ही लेन-देन के लिए बनाई गई हैं अगर एक अनुकूलन है। तो, यह ठीक क्यों होगा? जेडीबीसी स्तर पर लेनदेन एक कनेक्शन पर किया जाता है। जहां तक मुझे पता है, जेडीबीसी स्पेक एक कनेक्शन पर कई लेनदेन चलाने की विधि प्रदान नहीं करता है। इसका मतलब है कि यदि एक दृढ़ता संदर्भ के लिए काम किया जाता है, तो प्रतिबद्धता दूसरे के लिए भी होती है।
लेकिन वास्तव में यह है क्यों यह काम करता है। एक वितरित लेनदेन के लिए प्रतिबद्ध बिंदु कार्य करना चाहिए जैसे कि सभी हिस्सों में एक संपूर्ण रूप है (मतदान चरण में सभी मतदान "हां" मानते हैं)। इस मामले में, दोनों दृढ़ता संदर्भ एक ही कनेक्शन पर परिचालन कर रहे हैं, इसलिए वे पूरी तरह से काम की एक इकाई हैं। चूंकि लेनदेन कंटेनर द्वारा प्रबंधित किया जाता है, वैसे भी इसके लिए तत्काल पहुंच नहीं है, जिसका अर्थ है कि आप एक संदर्भ करने के लिए आगे नहीं बढ़ सकते हैं, न कि दूसरे। और वास्तव में लेनदेन के साथ पंजीकरण करने के लिए केवल एक कनेक्शन के साथ, यह एक्सए नहीं होना चाहिए, क्योंकि इसे लेनदेन प्रबंधक के दृष्टिकोण से वितरित नहीं माना जाता है।
ध्यान दें कि यह दृढ़ता संदर्भों के इलाके का उल्लंघन नहीं करता है। डेटाबेस परिणामों से किसी इकाई को दोनों संदर्भों में एक अलग ऑब्जेक्ट में प्राप्त करना। वे अभी भी एक दूसरे से स्वतंत्र रूप से काम कर सकते हैं, जैसे वे अलग कनेक्शन के साथ करेंगे। उपरोक्त आरेख में, एक ही प्राथमिक कुंजी के साथ उसी प्रकार की प्राप्त इकाइयां समान डेटाबेस पंक्ति का प्रतिनिधित्व करती हैं, लेकिन अलग-अलग ऑब्जेक्ट्स उनके संबंधित इकाई प्रबंधकों द्वारा प्रबंधित की जाती हैं।
यह सत्यापित करने के लिए कि यह वास्तव में जेपीए प्रदाता द्वारा कुछ अनुकूलन है, मैंने दूसरा कनेक्शन पूल (उसी डेटाबेस में) और एक अलग जेडीबीसी संसाधन बनाया है, इसे दूसरी दृढ़ता इकाई के लिए सेट किया है और परीक्षण किया है। यह उम्मीद अपवाद में परिणाम:
Caused by: java.sql.SQLException: Error in allocating a connection.
Cause: java.lang.IllegalStateException: Local transaction already has 1 non-XA Resource: cannot add more resources.
आप दो JDBC संसाधन बनाने, लेकिन एक ही कनेक्शन पूल करने के लिए दोनों इंगित करते हैं, तो फिर यह सिर्फ ठीक काम करता है।यह स्पष्ट रूप से कक्षा com.microsoft.sqlserver.jdbc.SQLServerConnectionPoolDataSource
का उपयोग करते समय भी काम करता है, यह पुष्टि करते हुए कि यह एक ही डेटा स्रोत (जो ग्लासफ़िश पूलिंग को पराजित करेगा) के लिए दो बार गलती से एक ही कनेक्शन प्राप्त करने के बजाय जेपीए स्तर पर एक अनुकूलन है। एक एक्सए डेटा स्रोत का उपयोग करते समय, यह वास्तव में एक एक्सए-सक्षम कनेक्शन होगा, लेकिन जेपीए प्रदाता अभी भी दृढ़ता संदर्भ दोनों के लिए एक ही उपयोग करेगा। केवल अलग पूल का उपयोग करते समय यह वास्तव में दो पूरी तरह से अलग एक्सए-सक्षम कनेक्शन होगा और अब आपको उपरोक्त अपवाद नहीं मिलेगा।
तो, कैच क्या है? सबसे पहले, मुझे जेपीए या जेटीए चश्मा में इस व्यवहार का वर्णन (या अनिवार्य) कुछ भी नहीं मिला है। इसका मतलब है कि यह शायद एक कार्यान्वयन-विशिष्ट अनुकूलन है। एक अलग जेपीए प्रदाता, या यहां तक कि एक अलग संस्करण में ले जाएं, और यह अब काम नहीं कर सकता है।
दूसरा, डेडलॉक्स प्राप्त करना संभव है। यदि आप उपरोक्त उदाहरण में इकाई को दोनों संदर्भों में लाते हैं, तो इसे एक में बदलें और फ्लश करें, यह ठीक है। इसे एक संदर्भ में लाएं, फ्लश विधि को कॉल करें और फिर इसे दूसरे में लाने का प्रयास करें, और आपके पास डेडलॉक हो सकता है। यदि आप पठन-रहित लेनदेन अलगाव की अनुमति देते हैं, तो आप इससे बचेंगे लेकिन एक संदर्भ में जो आप देखेंगे, उस पर निर्भर करेगा जब आप इसे दूसरे में फ्लश के सम्मान के साथ लाएंगे। तो मैन्युअल फ्लश कॉल मुश्किल हो सकता है।
संदर्भ के लिए, ग्लासफ़िश संस्करण का उपयोग 3.1.2.2
था। जेपीए प्रदाता हाइबरनेट संस्करण 3.6.4.Final
था।
टी एल; डॉ
हाँ, आप एक JavaEE कंटेनर से प्रबंधित लेन-देन में एक ही गैर-XA संसाधन के साथ दो हठ संदर्भों का उपयोग कर सकते हैं, और एसिड गुण संरक्षित कर रहे हैं। हालांकि, यह एक हाइबरनेट ऑप्टिमाइज़ेशन की संभावना है, जब एक ही डेटा स्रोत के साथ एक ही लेनदेन के लिए एकाधिक EntityManagers बनाए जाते हैं। चूंकि यह जेपीए या जेटीए चश्मा द्वारा अनिवार्य नहीं लगता है, इसलिए आप जेपीए कार्यान्वयन, संस्करण या एप्लिकेशन सर्वर पर इस व्यवहार पर भरोसा नहीं कर सकते हैं। तो परीक्षण करें और पूर्ण पोर्टेबिलिटी की उम्मीद न करें।
यदि दो दृढ़ता इकाइयां एक ही डेटास्रोत का उपयोग कर रही हैं तो आपको XA –
@SteveC की आवश्यकता नहीं होनी चाहिए, उन्हें पूल से अपना कनेक्शन मिल जाएगा, इसलिए मुझे उन्हें एक ही कनेक्शन रखने के लिए मजबूर करने का कोई तरीका नहीं दिख रहा है (और इस प्रकार लेनदेन) या जेपीए वास्तव में इसका प्रबंधन कैसे करेगा। –
मैं उम्मीद करता हूं कि वे दोनों एक ही जेटीए लेनदेन में भाग लेंगे ... –