2015-02-12 8 views
6

के साथ एक नया लेनदेन नहीं बनाता है मेरे पास निम्नलिखित परिदृश्य है। मैं जेपीए का उपयोग कर रहा हूं, वसंत:प्रचार। REQUIRES_NEW वसंत में जेपीए

@Autowired 
SampleService service; 

@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class) 
public void PerformLogic(LogicData data) throws SIASFaultMessage 
{ 
    SampleObject so = createSampleObject(); 

    try{ 
     .//do some logic to persist things in data 
     . 
     . 
     persistData(data); 
     . 
     . 
     . 


     updateSampleObject(so);  
    } 
    catch(Exception){ 
     updateSampleObject(so);  
     throw new SIASFaultMessage(); 
    } 

} 

@Transactional(propagation = Propagation.REQUIRES_NEW) 
public createSampleObject() 
{ 
    SampleObject so = new SampleObject(); 

    . 
    .//initialize so 
    . 

    service.persist(so);   
    return so; 
} 

@Transactional(propagation = Propagation.REQUIRES_NEW) 
public updateSampleObject(SampleObject so) 
{    
    service.persist(so);   
    return so; 
} 

जब सब कुछ ठीक काम करता है, डेटा बिना किसी समस्या के डेटाबेस में जारी रहता है। हालांकि, जब एक अपवाद फेंक दिया जाता है, तो मुझे यह आवश्यक है कि विधि अद्यतन नमूना ऑब्जेक्ट (इसलिए) डेटाबेस में जानकारी को जारी रखे। ऐसा नहीं हो रहा है। यदि कोई अपवाद फेंक दिया गया है तो अद्यतन SampleObject वापस भी घुमाया जाता है, जो मुझे चाहिए। मुझे लगता है कि इन दोनों तरीकों (createSampleObject और updateSampleObject) हर समय कोई फर्क नहीं पड़ता कि क्या एक अपवाद या नहीं फेंका गया कायम हो, की जरूरत है। मैं इसे कैसे प्राप्त कर सकता हूं?

इसके अलावा, अगर मैं तरीकों anotate createSampleObject और updateSampleObject साथ:

@Transactional(propagation = Propagation.NEVER) 

विचार है कि एक अपवाद फेंक दिया है और मैं कोई अपवाद नहीं फेंक दिया मिलता है। समस्या कहाँ हे? लॉग का विश्लेषण करते हुए मैं यह लाइन देखता हूं:

org.springframework.orm.jpa.JpaTransactionManager ==> Creating new transaction with name [com.test.PerformLogic]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT.... 

जिसका अर्थ यह लेनदेन बनाया गया है, लेकिन मुझे अन्य लेनदेन का कोई संकेत नहीं दिखता है।

इस वसंत के बारे में लेनदेन के लिए मेरी विन्यास फाइल का हिस्सा है

<bean id="myDataSource" 
     class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
    <property name="driverClassName" value="${jdbc.driverClassName}"/> 
    <property name="url" value="${jdbc.url}"/> 
    <property name="username" value="${jdbc.username}"/> 
    <property name="password" value="${jdbc.password}"/> 
</bean> 
<bean id="entityManagerFactory" 
     class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
    <property name="dataSource" ref="myDataSource"/> 
    <property name="packagesToScan" value="cu.jpa"/> 
    <property name="persistenceProviderClass" value="org.hibernate.ejb.HibernatePersistence"/> 
    <property name="jpaProperties"> 
     <props> 
      <prop key="hibernate.dialect">${hibernate.dialect}</prop> 
      <prop key="hibernate.show_sql">true</prop> 
      <prop key="hibernate.hbm2ddl.auto">${hdm2ddl.auto}</prop> 
     </props> 
    </property> 
    <property value="/META-INF/jpa-persistence.xml" name="persistenceXmlLocation"/> 
    <property name="persistenceUnitName" value="jpaPersistenceUnit"/> 
</bean> 

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> 
    <property name="entityManagerFactory" ref="entityManagerFactory"/> 
    <property name="nestedTransactionAllowed" value="true" /> 
</bean> 

<tx:annotation-driven transaction-manager="transactionManager"/> 

उत्तर

22

वसंत लेनदेन प्रॉक्सी-आधारित हैं। इस प्रकार यह कैसे काम करता है जब बीन ए बीन बी के लेनदेन का कारण बनता है। ए वास्तव में एक प्रॉक्सी का संदर्भ है, जो बीन बी को प्रतिनिधि करता है। यह प्रॉक्सी वह है जो लेनदेन शुरू करता है और करता है/लेनदेन करता है:

A ---> proxy ---> B 

आपके कोड में, ए की एक लेनदेन विधि ए की एक और लेनदेन विधि कहती है तो वसंत कॉल को रोक नहीं सकता और एक नया लेनदेन शुरू नहीं कर सकता है। यह किसी भी प्रॉक्सी शामिल किए बिना एक नियमित विधि कॉल है।

तो, यदि आप एक नया लेनदेन शुरू करना चाहते हैं, तो विधि createSampleObject() किसी अन्य बीन में होनी चाहिए, जो आपके वर्तमान बीन में इंजेक्शन दी जानी चाहिए।

यह the documentation में अधिक जानकारी के साथ समझाया गया है।

+1

धन्यवाद, वह था। मैं वसंत दस्तावेज के करीब एक नज़र डालेंगे। क्या आपको पता है कि लेन-देन प्रॉक्सी-आधारित पर काम करने का कोई तरीका नहीं है, लेकिन विधि पर? –

+1

@ अल्फ्रेडोए। यह संभव है यदि आप अपने कोड को बाधित करने के लिए AspectJ लोड-टाइम बुनाई का उपयोग करते हैं, जिससे उपर्युक्त वर्णित प्रॉक्सी की आवश्यकता पर रोक लगा दी जाती है। इस तरह, कक्षा ए के लेन-देन विधि foo() क्लास ए के लेनदेन संबंधी विधि बार() को भी कॉल कर सकते हैं, और बार() अपने लेनदेन के अंदर चलाएगा। इस पर अधिक जानकारी के लिए, उपरोक्त लिंक स्प्रिंग फ्रेमवर्क दस्तावेज से परामर्श लें। – Aquarelle

+0

धन्यवाद एक टन।जब लेनदेन किया जाता है तो मैंने बहुत कुछ खोजा क्योंकि मेरे पास 2 अलग-अलग लेनदेन हैं जहां कोई दूसरे के नतीजे पर निर्भर है। यह "आवश्यक" और "Requires_New" के साथ काम करता था, लेकिन केवल तभी जब मैंने अलग सेम में रखा था। –

4

मेरा अनुमान है कि के बाद से दोनों तरीकों एक ही सेम में हैं, वसंत के AOP बनाने/updateSampleObject अवरोधन करने का मौका नहीं है विधि कॉल विधियों को एक अलग बीन में ले जाने का प्रयास करें।

+0

बहुत बहुत धन्यवाद, यह था। मैं इसे सही के रूप में चिह्नित करूंगा, लेकिन मैंने पहले दूसरे को पढ़ा था। –

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