एनोटेशन @ ट्रैंसैशनल। रोलबैक कैसे करें?


91

मैंने एक डाओ क्लास के लिए इस एनोटेशन का सफलतापूर्वक उपयोग किया। और रोलबैक परीक्षणों के लिए काम करता है।

लेकिन अब मुझे असली कोड रोलबैक करने की जरूरत है, न केवल परीक्षण। परीक्षणों में उपयोग के लिए विशेष एनोटेशन हैं। लेकिन गैर-परीक्षण कोड के लिए कौन से एनोटेशन हैं? मेरे लिए यह एक बड़ा सवाल है। मैंने पहले से ही उसके लिए एक दिन बिताया। आधिकारिक दस्तावेज मेरी जरूरतों को पूरा नहीं करते थे।

class MyClass { // this does not make rollback! And record appears in DB.
        EmployeeDaoInterface employeeDao;

        public MyClass() {
            ApplicationContext context = new ClassPathXmlApplicationContext(
                    new String[] { "HibernateDaoBeans.xml" });
            employeeDao = (IEmployeeDao) context.getBean("employeeDao");
         }

        @Transactional(rollbackFor={Exception.class})
    public void doInsert( Employee newEmp ) throws Exception {
        employeeDao.insertEmployee(newEmp);
        throw new RuntimeException();
    }
}

कर्मचारीडाओ है

@Transactional
public class EmployeeDao implements IEmployeeDao {
    private SessionFactory sessionFactory;

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    public void insertEmployee(Employee emp) {
        sessionFactory.getCurrentSession().save(emp);
    }
}

और यहाँ एक परीक्षण है जिसके लिए एनोटेशन अच्छी तरह से काम करते हैं:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "/HibernateDaoBeans.xml" })
@TransactionConfiguration(transactionManager = "txManager", defaultRollback = true)
@Transactional
public class EmployeeDaoTest {

    @Autowired
    EmployeeDaoInterface empDao;

    @Test
    public void insert_record() {
       ...
       assertTrue(empDao.insertEmployee(newEmp));
    }

HibernateDaoBeans.xml

   ...
<bean id="employeeDao" class="Hibernate.EmployeeDao">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>
    <tx:annotation-driven transaction-manager="txManager"/>

<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>
   ...



** हाँ, मैंने लेन-देन वापस किया। मैंने अभी सेवा के लिए BEAN जोड़ा है ... और फिर एनोटेशन @ ट्रेंसेशनल काम शुरू करने के लिए :-) :)

<bean id="service" class="main.MyClass">
    <property name="employeeDao" ref="employeeDao" />
</bean>

सभी का धन्यवाद, रूस आपको नहीं भूलेगा!

जवाबों:


163

बस RuntimeExceptionके रूप में चिह्नित विधि से किसी भी फेंक दें @Transactional

डिफ़ॉल्ट रूप से सभी RuntimeExceptionरोलबैक लेन-देन जबकि चेक किए गए अपवाद नहीं हैं। यह एक ईजेबी विरासत है। आप इसका उपयोग करके rollbackFor()और noRollbackFor()एनोटेशन मापदंडों को कॉन्फ़िगर कर सकते हैं :

@Transactional(rollbackFor=Exception.class)

यह किसी भी अपवाद को फेंकने के बाद लेनदेन को रोलबैक करेगा ।


1
मैं इसे करने की कोशिश की। यह काम नहीं करता! मैं सीधे डाओ ऑब्जेक्ट में रोलबैक ऑपरेशन के बारे में नहीं बताता, जो काम कर सकता है। मैं एक अन्य ऑब्जेक्ट के बारे में बताता हूं जो डाओ मेथोडा के कॉल के अनुक्रम का उपयोग करता है जो @ ट्रान्सएक्टेंशनल का उपयोग करता है। और मैं अपनी कक्षा के लिए वही एनोटेशन जोड़ने की कोशिश करता हूं जो इस डाओ को कहते हैं। लेकिन यहां काम नहीं होता।
मॉस्को ब्वॉय

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

पहले पोस्ट में जोड़े गए कोड को देखें। मेरे पास कोड का एक हिस्सा है। और निष्पादन के बाद मेरे पास डीबी में रिकॉर्ड है। => रोलबैक अभी तक काम नहीं करता है।
मॉस्को बॉय 8

क्या डीएओ से एक अपवाद को फेंकने से लेनदेन वापस नहीं होता है? क्या आपने org.springframework.orm.hibernate3.HibernateTransactionManagerअपने स्प्रिंग संदर्भ में कॉन्फ़िगर किया है? यदि आप org.springframework.transactionलकड़हारा सक्षम करते हैं , तो क्या यह कुछ दिलचस्प दिखाता है?
टॉमाज़ नर्कविक्ज़

1
यदि आप स्प्रिंग बूट का उपयोग कर रहे हैं और इसे डेटा स्रोत को ऑटो-कॉन्फ़िगर करते हैं, तो यह HikariDataSource का उपयोग करेगा जो डिफ़ॉल्ट रूप से ऑटो-कम सेट को सही करने के लिए है। आपको इसे गलत पर सेट करने की आवश्यकता है: hikariDataSource.setAutoCommit (गलत); मैंने DataSourceTransactionManager बीन को कॉन्फ़िगर करते समय @Configuration क्लास में यह बदलाव किया।
एलेक्स

83

या प्रोग्रामिक रूप से

TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

12
हाँ। क्योंकि कभी-कभी आपको एक त्रुटि फेंकने के बिना रोलबैक करने की आवश्यकता होती है।
एरिका केन

2
आप एक जीवन रक्षक है।
दीवार

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

2
कभी-कभी यह काम नहीं करता है। उदाहरण के लिए, मेरे मामले में मेरे पास एक लेन-देन सेवा और गैर-लेन-देन भंडार है। मैं सेवा से रिपॉजिटरी को कॉल करता हूं, इसलिए, इसे सेवा द्वारा खोले गए लेनदेन में भाग लेना चाहिए। लेकिन अगर मैं आपके कोड को मेरे गैर-ट्रांसेक्शनल रिपॉजिटरी से कॉल करता हूं, तो यह इस तथ्य के बावजूद NoTransactionException को फेंकता है कि लेनदेन मौजूद है।
विक्टर डोंब्रोव्स्की

3
आप अपने "गैर-लेन-देन भंडार" में कौन सा लेन-देन वापस करना चाहते हैं?
स्टीफन के।

5

आप उस विधि से एक अनियंत्रित अपवाद को फेंक सकते हैं जिसे आप वापस रोल करना चाहते हैं। यह वसंत द्वारा पता लगाया जाएगा और आपके लेनदेन को केवल रोलबैक के रूप में चिह्नित किया जाएगा।

मैं मान रहा हूँ कि आप यहाँ स्प्रिंग का उपयोग कर रहे हैं। और मुझे लगता है कि आपके परीक्षण में आपके द्वारा निर्दिष्ट एनोटेशन स्प्रिंग टेस्ट आधारित एनोटेशन हैं।

स्प्रिंग फ्रेमवर्क के लेन-देन के बुनियादी ढाँचे को इंगित करने का अनुशंसित तरीका है कि लेन-देन का काम वापस लेना है, एक अपवाद को उस कोड से फेंकना है जो वर्तमान में लेनदेन के संदर्भ में निष्पादित हो रहा है।

और ध्यान दें कि:

कृपया ध्यान दें कि स्प्रिंग फ्रेमवर्क का ट्रांजेक्शन इन्फ्रास्ट्रक्चर कोड, डिफ़ॉल्ट रूप से, केवल रनटाइम, अनियंत्रित अपवादों के मामले में रोलबैक के लिए लेनदेन को चिह्नित करेगा; जब फेंक अपवाद RuntimeException का एक उदाहरण या उपवर्ग है।


1

मेरे लिए रोलबैकफ़ोर पर्याप्त नहीं था, इसलिए मुझे इसे लगाना पड़ा और यह उम्मीद के मुताबिक काम करता है:

@Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = Exception.class)

मुझे उम्मीद है यह मदद करेगा :-)


1
नहीं, यह TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();आपकी मदद के नीचे बिल्कुल भी मदद नहीं करता है
Enerccio
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.