2012-04-10 30 views
5

मैं MySQL 5.5 सर्वर पर SQL क्वेरी के बैच चलाने के लिए स्प्रिंग-आधारित समाधान बनाने की कोशिश कर रहा हूं। "क्वेरी" से मेरा मतलब है कि कोई भी SQL कथन जो संकलित करता है, इसलिए SQL बैच नौकरी में उदाहरण के लिए कई CREATE तालिका, हटाएं और फिर INSERT कथन शामिल हो सकते हैं।स्प्रिंग ट्रांजैक्शन मैनेजर - प्रतिबद्ध काम नहीं करता

मैं इस उद्देश्य के लिए Spring Batch का उपयोग कर रहा हूं।

मेरे पास transactionManager निम्नानुसार कॉन्फ़िगर किया गया है।

<bean id="transactionManager" 
     class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
     <property name="dataSource" ref="dataSource" /> 
    </bean> 
    <tx:annotation-driven transaction-manager="transactionManager" /> 

और dataSource:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" 
    destroy-method="close"> 
    <property name="driverClassName" value="${batch.jdbc.driver}" /> 
    <property name="url" value="${batch.jdbc.url}" /> 
    <property name="username" value="${batch.jdbc.user}" /> 
    <property name="password" value="${batch.jdbc.password}" /> 
    <property name="maxIdle" value="10" /> 
    <property name="maxActive" value="100" /> 
    <property name="maxWait" value="10000" /> 
    <property name="validationQuery" value="select 1" /> 
    <property name="testOnBorrow" value="false" /> 
    <property name="testWhileIdle" value="true" /> 
    <property name="timeBetweenEvictionRunsMillis" value="1200000" /> 
    <property name="minEvictableIdleTimeMillis" value="1800000" /> 
    <property name="numTestsPerEvictionRun" value="5" /> 
    <property name="defaultAutoCommit" value="true" /> 
</bean> 

मेरे डीएओ वर्ग विधि एकल एसक्यूएल बयान के साथ विधि बुला SQL कथन का एक संग्रह से अधिक

@Transactional(propagation = Propagation.REQUIRES_NEW) 

और मैं पाश के साथ विन्यस्त है एक वक़्त।

simpleJdbcTemplate.getJdbcOperations().execute(sql); 

मैं उम्मीद है कि जब डीएओ विधि पूरा करता है, मैं डीबी में परिणाम देखेंगे: प्रसंस्करण विधि के अंदर के रूप में सरल रूप में है। हालांकि, ऐसा लगता है कि वसंत नौकरी निष्पादन पूरा होने पर परिणाम डीबी में उपलब्ध हो जाते हैं।

मैं करने की कोशिश की मेरी डीएओ विधि के अंदर प्रतिबद्ध:

@Transactional(propagation = Propagation.REQUIRES_NEW) 
private void executeSingleQuery(String sql) { 
    PlatformTransactionManager transactionManager = (PlatformTransactionManager)context.getBean("transactionManager"); 


    DefaultTransactionDefinition def = new DefaultTransactionDefinition(); 
    def.setPropagationBehavior(Propagation.REQUIRED.ordinal()); 

    TransactionStatus status = transactionManager.getTransaction(def); 

    try { 
     // execute your business logic here 
     log.info("about to execute SQL query[" + sql + "]"); 
     simpleJdbcTemplate.getJdbcOperations().execute(sql); 

    } catch (Exception e) { 
     log.info("SQL query was not committed due to exception and was marked for rollback"); 
     transactionManager.rollback(status); 
    } 

    transactionManager.commit(status); 

    if (transactionManager.getTransaction(null).isRollbackOnly() 
      && transactionManager.getTransaction(null).isCompleted()) { 
     log.info("SQL query commited!"); 
    } else { 
     log.info("SQL query was not committed due to: 1) the transaction has been marked for rollback " + 
       "2) the transaction has not completed for some reason"); 
    } 

    log.info("the query has completed"); 
} 

मैं वसंत कोड डिबग और देखा कि मैं अपने लिए प्रतिबद्ध डीएओ विधि से फोन (प्रवाह लाइन तक पहुँच जाता TransactionTemplate द्वारा निष्पादित किया जाता है this.transactionManager.commit(status); और अपवादों के बिना गुजरता है)

मैं किसी भी सलाह की सराहना करता हूं कि प्रत्येक कॉल पर डीएओ विधि को प्रतिबद्ध करने के लिए क्या किया जाना चाहिए (प्रत्येक SQL कथन के बाद प्रतिबद्ध करें)।

+0

@ ट्रांसेक्शन एनोटेशन करने का ख्याल रखता है। आपके कोड में आपको लेनदेन प्रबंधक के संदर्भ की आवश्यकता नहीं है और मुझे लगता है कि बदलाव स्पष्ट रूप से करें। – ch4nd4n

उत्तर

8

आप निजी विधियों को प्रॉक्सी नहीं कर सकते हैं। यानी आपके यहां @ ट्रान्सैक्शनल का कोई प्रभाव नहीं है। विधि को अपने पैरेंट इंटरफ़ेस पर खींचें और इसे काम करना चाहिए। जब तक आपके पास proxyTargetClass सेटिंग सक्षम नहीं है, जिसे अनुशंसित नहीं किया जाता है।

+0

ने डीएओ विधि को सार्वजनिक में बदल दिया - एक ही समस्या – aviad

+1

पैरेंट इंटरफ़ेस को विधि खींचने से स्थिति में मदद मिली। Shukran!:) – aviad

3

जब आप उसी श्रेणी के भीतर से अपने executeSingleQuery() पर कॉल करते हैं तो आप प्रॉक्सी के माध्यम से नहीं जा रहे हैं, इसलिए लेनदेन संबंधी एनोटेशन का कोई प्रभाव नहीं पड़ेगा।

आप कथात्मक और कार्यक्रम संबंधी लेन-देन मिश्रण कर रहे हैं, मुमकिन है आप जब अपने DefaultTransactionDefinition की स्थापना REQUIRES_NEW तो आप व्यर्थ @Transactional टिप्पणी निकालने और Propagation.REQUIRES_NEW इस्तेमाल कर सकते हैं चाहता हूँ।

इसके अलावा, आप try ब्लॉक के अंदर transactionManager.commit(status) स्थानांतरित करने के लिए चाहते हो सकता है, अपने वर्तमान कोड वापस रोल है, तो एक के लिए प्रतिबद्ध एक Exception तब होता है जब प्रयास करता है।

+0

धन्यवाद, मैं आपके उत्तर को ऊपर उठाता हूं क्योंकि यह सहायक था (इसका हिस्सा)। हालांकि मैं 2 उत्तरों को स्वीकार नहीं कर सकता- और माधेतो उत्तर देने वाला पहला था ... – aviad

0

हमने @Rollback(value = false) एनोटेशन का उपयोग किया और यह उस समस्या को ठीक कर दिया जिसकी आप सामना कर रहे हैं।