"यदि कोई कर्मचारी अपना काम अच्छी तरह से करना चाहता है, तो उसे पहले अपने औजारों को तेज करना होगा।" - कन्फ्यूशियस, "द एनालेक्ट्स ऑफ कन्फ्यूशियस। लू लिंगगोंग"
मुखपृष्ठ > प्रोग्रामिंग > एक सामान्य रूपरेखा के साथ जाने में मजबूत SQL लेनदेन निष्पादन का निर्माण

एक सामान्य रूपरेखा के साथ जाने में मजबूत SQL लेनदेन निष्पादन का निर्माण

2025-03-23 ​​पर पोस्ट किया गया
ब्राउज़ करें:213

] इस लेख में, मैं आपको लचीलेपन के लिए जेनरिक का उपयोग करके, GO में SQL लेनदेन को निष्पादित करने के लिए एक मजबूत, पुन: प्रयोज्य और परीक्षण योग्य ढांचा बनाने के माध्यम से मार्गदर्शन करूंगा।

] यह दोनों स्टेटलेस और स्टेटफुल ऑपरेशंस का समर्थन करता है, जो कि संबंधित संस्थाओं को सम्मिलित करने जैसे परिष्कृत वर्कफ़्लो को सक्षम करता है, जबकि निर्भरता को मूल रूप से प्रबंधित करता है। Building Robust SQL Transaction Execution in Go with a Generic Framework

हमें SQL लेनदेन के लिए एक रूपरेखा की आवश्यकता क्यों है?

वास्तविक दुनिया के अनुप्रयोगों में, डेटाबेस संचालन शायद ही कभी अलग-थलग हो जाते हैं। इन परिदृश्यों पर विचार करें:

एक उपयोगकर्ता को सम्मिलित करना और उनकी इन्वेंट्री को अद्यतन करना।

एक आदेश बनाना और इसके भुगतान को संसाधित करना, स्थिरता सुनिश्चित करना।

शामिल कई चरणों के साथ, विफलताओं के दौरान रोलबैक का प्रबंधन करना डेटा अखंडता सुनिश्चित करने के लिए महत्वपूर्ण हो जाता है।

TXN प्रबंधन में GO के साथ काम करना।

] जबकि यह TXN प्रबंधन जावा में स्प्रिंग बूट द्वारा प्रबंधित किया जाता है और आपने जावा में कोड लिखते समय उन लोगों पर कभी ज्यादा परेशान नहीं किया, लेकिन गोलंग में ऐसा नहीं है। एक सरल उदाहरण नीचे दिया गया है

] // एक लेनदेन शुरू करें TX, ERR: = DB.BEGIN () अगर गलत! = nil { वापसी की कमी } टेंक फंक () { यदि r: = पुनर्प्राप्त (); r! = nil { tx.rollback () } और अगर गलत! = nil { tx.rollback () } अन्य { tx.commit () } } () // ऑर्डर तालिका में डेटा डालें _, ERR = TX.EXEC ("ऑर्डर में डालें (ID, CUSTOME_NAME, ORDER_DATE) मान (1, 'जॉन डो', '2022-01-01')") ")") ")") ")") ")") ")") ")") ")") ") अगर गलत! = nil { वापसी की कमी } वापसी निल }

हम हर फ़ंक्शन के लिए रोलबैक/कमिट कोड को दोहराने की उम्मीद नहीं कर सकते। हमारे पास दो विकल्प हैं या तो या तो एक क्लास बनाते हैं जो एक फ़ंक्शन को एक रिटर्न प्रकार के रूप में प्रदान करेगा, जो जब डिफेर में निष्पादित किया जाएगा/रोलबैक TXN होगा या एक रैपर क्लास बनाएगा, जो सभी TXN फंक को एक साथ लपेटेगा और एक बार में निष्पादित करेगा।

मैं बाद की पसंद के साथ गया और कोड में परिवर्तन नीचे देखा जा सकता है।

] db: = setupdatabase () // एक नया SQL लिखें निष्पादक बनाएँ ERR: = dbutils.newsqltxnexec [OrderRequest, orderProcessingResponse] (conferving.todo (), db, nil, & orderrequest {customerName: "CustomerAme", productId: 1, 1, मात्रा: 10})। Statefulexec (INSERTORDOR)। Statefulexec (UpdateInventory)। Statefulexec (सम्मिलन)। प्रतिबद्ध() // जाँच करें कि क्या लेनदेन सफलतापूर्वक किया गया था अगर गलत! = nil { टी.फैटल (एर) वापस करना } VerifyTransactionsuccessful (टी, डीबी) t.cleanup ( func () { क्लीनअप (डीबी) db.close () }, ) }
func basicTxn(db *sql.DB) error {
    // start a transaction
    tx, err := db.Begin()
    if err != nil {
        return err
    }
    defer func() {
        if r := recover(); r != nil {
            tx.Rollback()
        } else if err != nil {
            tx.Rollback()
        } else {
            tx.Commit()
        }
    }()

    // insert data into the orders table
    _, err = tx.Exec("INSERT INTO orders (id, customer_name, order_date) VALUES (1, 'John Doe', '2022-01-01')")
    if err != nil {
        return err
    }
    return nil
}

यह कोड बहुत अधिक सटीक और संक्षिप्त होगा।

कोर लॉजिक कैसे लागू किया जाता है
] TXN द्वारा मेरा मतलब है कि कार्य जो TXN के साथ कार्रवाई करेंगे जो हमने कक्षा के लिए बनाया था।

func TestSqlWriteExec_CreateOrderTxn(t *testing.T) {

    db := setupDatabase()
    // create a new SQL Write Executor
    err := dbutils.NewSqlTxnExec[OrderRequest, OrderProcessingResponse](context.TODO(), db, nil, &OrderRequest{CustomerName: "CustomerA", ProductID: 1, Quantity: 10}).
        StatefulExec(InsertOrder).
        StatefulExec(UpdateInventory).
        StatefulExec(InsertShipment).
        Commit()
    // check if the transaction was committed successfully
    if err != nil {
        t.Fatal(err)
        return
    }
    verifyTransactionSuccessful(t, db)
    t.Cleanup(
        func() { 
            cleanup(db)
            db.Close() 
        },
    )
}
] अब डेटा लेयर में इस तरह से एक फ़ंक्शन बनाएं और इसे निष्पादक वर्ग को पास करें जो ARGS को इंजेक्ट करने और फ़ंक्शन को निष्पादित करने का ध्यान रखता है।
func InsertOrder(ctx context.Context, txn *sql.Tx, order *OrderRequest, orderProcessing *OrderProcessingResponse) error {
    // Insert Order
    result, err := txn.Exec("INSERT INTO orders (customer_name, product_id, quantity) VALUES ($1, $2, $3)", order.CustomerName, order.ProductID, order.Quantity)
    if err != nil {
        return err
    }
    // Get the inserted Order ID
    orderProcessing.OrderID, err = result.LastInsertId()
    return err
}

func UpdateInventory(ctx context.Context, txn *sql.Tx, order *OrderRequest, orderProcessing *OrderProcessingResponse) error {
    // Update Inventory if it exists and the quantity is greater than the quantity check if it exists
    result, err := txn.Exec("UPDATE inventory SET product_quantity = product_quantity - $1 WHERE id = $2 AND product_quantity >= $1", order.Quantity, order.ProductID)
    if err != nil {
        return err
    }
    // Get the number of rows affected
    rowsAffected, err := result.RowsAffected()
    if rowsAffected == 0 {
        return errors.New("Insufficient inventory")
    }
    return err
}

func InsertShipment(ctx context.Context, txn *sql.Tx, order *OrderRequest, orderProcessing *OrderProcessingResponse) error {
    // Insert Shipment
    result, err := txn.Exec("INSERT INTO shipping_info (customer_name, shipping_address) VALUES ($1, 'Shipping Address')", order.CustomerName)
    if err != nil {
        return err
    }
    // Get the inserted Shipping ID
    orderProcessing.ShippingID, err = result.LastInsertId()
    return err
}
] // आश्रित लिखते हैं कि आपको ProcessReq में आश्रित डेटा जोड़ने और अगले फ़ंक्शन कॉल पर आगे बढ़ने की आवश्यकता हो सकती है टाइप sqltxnexec [t कोई भी, r कोई भी] संरचना { db *sql.db txn *sql.tx txnfns [] txnfn [t] StateFultXnfns [] StateFultXnfn [T, R] प्रसंस्करण प्रीक्यू *टी Processedres *r CTX संदर्भ ।context गलत त्रुटि }

]

] टेंक फंक () { यदि p: = reame (); p! = nil { s.txn.rollback () घबराहट (पी) } और अगर गलत! = nil { Err = Errors.join (Err, S.TXN.ROLLBACK ()) } अन्य { Err = Errors.join (Err, S.TXN.Commit ()) } वापस करना } () _ के लिए, writefn: = रेंज s.txnfns { यदि err = writefn (s.ctx, s.txn, s.processingreq); irr! = nil { वापस करना } } _ के लिए, StatefulWriteFn: = रेंज S.StateFultXnfns { यदि ERR = STATEFULWRITEFN (S.CTX, S.TXN, S.ProcessingReq, S.Processedres); irr! = nil { वापस करना } } वापस करना }

आप रेपो में अधिक उदाहरण और परीक्षण पा सकते हैं -

https://github.com/mahadev-k/go-utils/tree/main/examples
]

मुझे बताएं कि क्या कोई इसके शीर्ष पर योगदान और निर्माण करना चाहता है !! यहां तक ​​इसे पढ़ने के लिए धन्यवाद!!
type TxnFn[T any] func(ctx context.Context, txn *sql.Tx, processingReq *T) error
type StatefulTxnFn[T any, R any] func(ctx context.Context, txn *sql.Tx, processingReq *T, processedRes *R) error
https://x.com/mahadev_k_


विज्ञप्ति वक्तव्य इस लेख को पुन: प्रस्तुत किया गया है: https://dev.to/mahadev_k/building-robust-sql-transaction-execution-in-go-with-with-a-generic-framework-4j0f?1 यदि कोई उल्लंघन है, तो कृपया इसे हटाने के लिए [email protected] पर संपर्क करें।
नवीनतम ट्यूटोरियल अधिक>

चीनी भाषा का अध्ययन करें

अस्वीकरण: उपलब्ध कराए गए सभी संसाधन आंशिक रूप से इंटरनेट से हैं। यदि आपके कॉपीराइट या अन्य अधिकारों और हितों का कोई उल्लंघन होता है, तो कृपया विस्तृत कारण बताएं और कॉपीराइट या अधिकारों और हितों का प्रमाण प्रदान करें और फिर इसे ईमेल पर भेजें: [email protected] हम इसे आपके लिए यथाशीघ्र संभालेंगे।

Copyright© 2022 湘ICP备2022001581号-3