Oracle
 sql >> डेटाबेस >  >> RDS >> Oracle

अगर बी गलत हो जाता है तो ए को वापस रोल करें। स्प्रिंग बूट, jdbctemplate

@Transactional वसंत में एनोटेशन आपके ऑब्जेक्ट को प्रॉक्सी में लपेटकर काम करता है जो बदले में @Transactional के साथ एनोटेट किए गए तरीकों को लपेटता है एक लेन-देन में। क्योंकि यह एनोटेशन निजी तरीकों पर काम नहीं करेगा (जैसा कि आपके उदाहरण में है) क्योंकि निजी तरीके इनहेरिट नहीं किए जा सकते हैं => उन्हें लपेटा नहीं जा सकता (यह सच नहीं है यदि आप पहलू के साथ घोषणात्मक लेनदेन का उपयोग करते हैं, तो नीचे प्रॉक्सी से संबंधित चेतावनी लागू नहीं होती हैं)।

कैसे @Transactional . की बुनियादी व्याख्या यहां दी गई है वसंत जादू काम करता है।

आपने लिखा:

class A {
    @Transactional
    public void method() {
    }
}

लेकिन जब आप बीन इंजेक्ट करते हैं तो आपको वास्तव में यही मिलता है:

class ProxiedA extends A {
   private final A a;

   public ProxiedA(A a) {
       this.a = a;
   }

   @Override
   public void method() {
       try {
           // open transaction ...
           a.method();
           // commit transaction
       } catch (RuntimeException e) {
           // rollback transaction
       } catch (Exception e) {
           // commit transaction
       }
   }
} 

इसकी सीमाएँ हैं। वे @PostConstruct . के साथ काम नहीं करते हैं विधियाँ क्योंकि उन्हें वस्तु के समीप होने से पहले बुलाया जाता है। और भले ही आपने सभी सही तरीके से कॉन्फ़िगर किया हो, लेन-देन केवल अनचेक . पर ही वापस रोल किए जाते हैं डिफ़ॉल्ट रूप से अपवाद। @Transactional(rollbackFor={CustomCheckedException.class}) . का उपयोग करें अगर आपको कुछ चेक किए गए अपवाद पर रोलबैक की आवश्यकता है।

एक और बार-बार सामने आने वाली चेतावनी मुझे पता है:

@Transactional विधि केवल तभी काम करेगी जब आप इसे "बाहर से" कहते हैं, निम्नलिखित उदाहरण में b() लेन-देन में लपेटा नहीं जाएगा:

class X {
   public void a() {
      b();
   }

   @Transactional
   public void b() {
   }
}

ऐसा इसलिए भी है क्योंकि @Transactional आपकी वस्तु को प्रॉक्सी करके काम करता है। ऊपर के उदाहरण में a() कॉल करेंगे X.b() उन्नत "स्प्रिंग प्रॉक्सी" विधि नहीं b() इसलिए कोई लेन-देन नहीं होगा। वर्कअराउंड के रूप में आपको b() . पर कॉल करना होगा दूसरे सेम से।

जब आप इनमें से किसी भी चेतावनी का सामना करते हैं और सुझाए गए समाधान का उपयोग नहीं कर सकते हैं (विधि को गैर-निजी बनाएं या b() पर कॉल करें। दूसरे बीन से) आप TransactionTemplate का उपयोग कर सकते हैं घोषणात्मक लेनदेन के बजाय:

public class A {
    @Autowired
    TransactionTemplate transactionTemplate;

    public void method() {
        transactionTemplate.execute(status -> {
            A();
            B();
            return null;
        });
    }

...
} 

अपडेट करें

उपरोक्त जानकारी का उपयोग करके ओपी अद्यतन प्रश्न का उत्तर देना।

<ब्लॉकक्वॉट>

@Transactional के साथ किस विधि को एनोटेट किया जाना चाहिए:परिवर्तन ()? डेटाबेस चेंज ()?

@Transactional(rollbackFor={Exception.class})
public void changes() throws Exception {
    someLogicBefore();
    databaseChanges();
    someLogicAfter();
}

सुनिश्चित करें कि changes() एक बीन के "बाहर से" कहा जाता है, कक्षा से ही नहीं और संदर्भ के बाद तत्काल किया गया था (उदाहरण के लिए यह afterPropertiesSet() नहीं है या @PostConstruct एनोटेट विधि)। समझें कि स्प्रिंग रोलबैक लेनदेन केवल डिफ़ॉल्ट रूप से अनियंत्रित अपवादों के लिए होता है (रोलबैक में अधिक विशिष्ट होने का प्रयास करेंचेक अपवाद सूची के लिए)।



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. RMAN और ORA-00245 . के साथ स्नैपशॉट नियंत्रण फ़ाइल सुविधा

  2. ऑरैकल में किसी उपयोगकर्ता से सभी विशेषाधिकार कैसे दिखाएं?

  3. Oracle डेटाबेस में श्रोता को कॉन्फ़िगर करना (12c, 18c और 19c संस्करण)

  4. SEC_CASE_SENSTIVE_LOGON 12c . में

  5. एसक्यूएल सिलेक्ट सिंबल क्या करता है || अर्थ?