6

मेरे पास डेटा एक्सेस क्लास है जो स्टैंड-अलोन जावा एप्लिकेशन के हिस्से के रूप में चलती है। वर्तमान में यह काम कर रहा है जिसका मतलब है कि एक लेनदेन प्रबंधक परिभाषित किया गया है, लेकिन मैं लेनदेन के दायरे को कम करने के लिए कक्षा को दोबारा प्रतिक्रिया देना चाहता हूं, लेकिन अगर मुझे लगता है कि मुझे org.hibernate.HibernateException: कोई हाइबरनेट सत्र थ्रेड से बंधे नहीं है, और कॉन्फ़िगरेशन नहीं करता है पर गैर-लेन-देन के निर्माण की अनुमति दें जो दर्शाती है कि @ ट्रांसेक्शन को किसी भी तरह से पहचानने से रोक दिया गया है।गैर-लेनदेन वाले हिस्सों को विभाजित करने के लिए आप @ ट्रान्सएक्शनल विधि को दोबारा कैसे प्रतिक्रिया देते हैं

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

public class DoStuff { 
    @Transactional 
    public void originalMethod() { 
     // do database stuff 
     ... 

     // do non-database stuff that is time consuming 
     ... 
    } 
} 

मुझे क्या करना चाहते हैं निम्नलिखित

public class DoStuff { 
    public void originalMethod() { 
     doDatabaseStuff() 

     doNonDatabaseStuff() 
    } 

    @Transactional 
    public void doDatabaseStuff() { 
     ... 
    } 

    public void doNonDatabaseStuff() { 
     ... 
    } 
} 
+0

आपका लेन-देन प्रबंधक कहां है? क्या आप अधिक जानकारी जोड़ सकते हैं? – Chris

+0

क्या आपकी कक्षा DoStuff किसी भी इंटरफेस को लागू करती है? –

+0

कोई इंटरफेस नहीं है, और लेनदेन प्रबंधक को परिभाषित किया गया है क्योंकि यह मूल वर्ग के लिए काम करता है। –

उत्तर

6

संपादित करने के लिए refactor है:

आप how Spring proxying works को समझने के लिए समझने के लिए क्यों अपनी पुनर्रचना के काम नहीं करता है की जरूरत है।

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

@ ट्रान्सएक्शनल स्प्रिंग एओपी का उपयोग करता है, वसंत प्रॉक्सी का उपयोग करता है। इसका मतलब यह है कि जब आप किसी अन्य वर्ग से @ ट्रांसेक्शन विधि को कॉल करते हैं, तो वसंत प्रॉक्सी का उपयोग करेगा, इसलिए लेनदेन संबंधी सलाह लागू की जाएगी। हालांकि, यदि आप एक ही कक्षा से विधि को कॉल करते हैं, तो वसंत प्रॉक्सी के बजाय "यह" संदर्भ का उपयोग करेगा, ताकि लेनदेन संबंधी सलाह लागू नहीं की जाएगी।

मूल उत्तर:

यहाँ समान स्थिति में मेरे लिए काम किया है।

public class DoStuff implement ApplicationContextAware {  
private ApplicationContext CONTEXT; 
public void setApplicationContext(ApplicationContext context) throws BeansException { 
    CONTEXT = context; 
} 

    public void originalMethod() {   
     getSpringProxy().doDatabaseStuff()    
     doNonDatabaseStuff()  
    } 

    private DoStuff getSpringProxy() { 
     return context.getBean(this.getClass());  
    } 
    @Transactional  
    public void doDatabaseStuff() {   
     ...  
    }   

    public void doNonDatabaseStuff() {   
     ...  
    } 
} 

स्पष्टीकरण:

  1. , वर्ग ApplicationContextAware बनाओ तो यह संदर्भ के लिए एक संदर्भ है
  2. आप एक लेन-देन संबंधी विधि कॉल संदर्भ से वास्तविक वसंत प्रॉक्सी लाने के लिए की जरूरत है
  3. अपनी विधि को कॉल करने के लिए इस प्रॉक्सी का उपयोग करें, ताकि @ ट्रांसेक्शनल वास्तव में लागू हो।
+0

मूल वर्ग पहले से ही @ ट्रांसेक्शनल को पहचानता है और सही तरीके से काम करता है। यह केवल रिफैक्टरिंग के बाद काम करना बंद कर देता है। –

+0

@ माइकल रदरफर्ड मेरे संपादन को देखें – gresdiplitude

+0

यह मेरी समस्या है। धन्यवाद –

0

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

इंटरफेस के बारे में मैंने जो कारण पूछा वह डिफ़ॉल्ट विधि से संबंधित है जिसके द्वारा वसंत लेनदेन संबंधी व्यवहार - जेडीके गतिशील प्रॉक्सी लागू करता है।

यदि आपका वर्ग की वास्तविक परिभाषा है:

public class DoStuff implements Doable { 
    public void originalMethod() { 

    } 
} 

public interface Doable { 
    public void originalMethod(); 
} 

अगर यह वास्तव में संरचना है, जब आप नई संरचना वसंत में ले जाया गया नई doDatabaseStuff विधि प्रॉक्सी करने में सक्षम नहीं है।

आपके विकल्प इसे ठीक करने के:

  • अपने इंटरफेस के लिए नए तरीकों को जोड़े सुनिश्चित करना है कि वसंत कर सकते हैं प्रॉक्सी उन्हें
  • CGLIB आधारित प्रॉक्सी का उपयोग कर के लिए खिसकाएं (इन इंटरफेस पर भरोसा नहीं करते)
+0

कोई कक्षा एक पीओजेओ नहीं है, सभी इंटरफेस सभी –

+0

ओह ठीक से लागू नहीं हैं। फिर भी। यह सब सच है :) –

+0

मैं असहमत नहीं था (बस यह कह रहा था कि यह इस मामले में लागू नहीं हुआ था :-) –

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