2011-02-24 7 views
18

स्प्रिंग, एक विधि अगर एक पहले से ही नहीं है कि @Transactional साथ टिप्पणी की जाती है एक नया लेन-देन प्राप्त होगा प्राप्त नहीं करता है, लेकिन मैंने देखा है कि एक लेन-देन संबंधी विधि किसी भी प्राप्त नहीं करता है लेनदेन अगर इसे गैर-लेनदेन से बुलाया जाता है। कोड यहाँ है।@Transactional विधि किसी अन्य विधि से कहा जाता है एक सौदे

@Component 
public class FooDao { 
    private EntityManager entityManager; 

    @PersistenceContext 
    protected void setEntityManager(EntityManager entityManager) { 
     this.entityManager = entityManager; 
    } 

    @Transactional 
    public Object save(Object bean) { 
     return this.entityManager.merge(bean); 
    } 

    public Object saveWrap(Object bean) { 
     return save(bean); 
    } 
} 

@Component 
public class FooService { 
    private FooDao fooDao; 

    public void save(Object bean) { 
     this.fooDao.saveWrap(bean); // doesn't work. 
     this.fooDao.save(bean); // works 
    } 
} 

saveWrap() एक नियमित रूप से विधि है कि save() जो व्यवहार है कहता है, लेकिन saveWrap() कोई भी परिवर्तन जारी रहती है नहीं होगा।

मैं वसंत 3 उपयोग कर रहा हूँ और हाइबरनेट 3. मैं गलत यहाँ क्या कर रहा हूँ? धन्यवाद।

उत्तर

30

यह स्प्रिंग्स AOP की सीमाओं में से एक है। चूंकि दाओ बीन वास्तव में एक प्रॉक्सी है जब इसे वसंत द्वारा बनाया जाता है, इसका मतलब है कि एक ही कक्षा के भीतर से एक विधि को कॉल करने से सलाह (जो लेनदेन है) को कॉल नहीं किया जाएगा। यह किसी अन्य पॉइंटकट

+2

@Transactional के साथ saveWrap विधि को एनोटेट करने में कोई हानि नहीं है। लेन-देन प्रचार के साथ डिफ़ॉल्ट व्यवहार आवश्यक है जिसका मतलब है कि आप एक नेस्टेड लेन-देन प्राप्त करने के लिए थे, तो (यानी। आप आ लेन-देन में हैं और फिर आप एक और तरीका जो भी @Transactional है कहते हैं) बस होगा मौजूदा लेन-देन का उपयोग करने और नहीं बना एक और अगर आप डरते हैं तो –

+0

प्रॉक्सी पर cglib का उपयोग करने के बारे में कैसे? मुझे cglib प्रॉक्सी सलाह हर विधि याद है, भले ही आप इसे उसी कक्षा में बुलाएं। – hiway

11

हाँ, इस व्यवहार की उम्मीद है। @Transactional ऑब्जेक्ट के चारों ओर प्रॉक्सी बनाने के लिए वसंत को बताता है। प्रॉक्सी अन्य ऑब्जेक्ट्स से ऑब्जेक्ट को कॉल करता है। प्रॉक्सी वस्तु के भीतर कॉल को अवरुद्ध नहीं करता है।

आप इस काम करने के लिए, विधि है कि "बाहर" से शुरू हो जाती है पर @Transactional जोड़ने चाहते हैं।

+1

एक और विकल्प कक्षा के शीर्ष पर @Transactional() (संभावित रूप से readOnly = true/false, प्रचार = कुछ इत्यादि) के साथ लेनदेन के रूप में पूरे वर्ग को चिह्नित करेगा और फिर केवल पढ़ने और/या प्रचार को ओवरराइड कर देगा- आवश्यकतानुसार मूल्य प्रति विधि। – esaj

2

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

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