] इस लेख में, मैं आपको लचीलेपन के लिए जेनरिक का उपयोग करके, GO में 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 {
वापसी की कमी
}
वापसी निल
}
मैं बाद की पसंद के साथ गया और कोड में परिवर्तन नीचे देखा जा सकता है।
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) errorhttps://x.com/mahadev_k_
अस्वीकरण: उपलब्ध कराए गए सभी संसाधन आंशिक रूप से इंटरनेट से हैं। यदि आपके कॉपीराइट या अन्य अधिकारों और हितों का कोई उल्लंघन होता है, तो कृपया विस्तृत कारण बताएं और कॉपीराइट या अधिकारों और हितों का प्रमाण प्रदान करें और फिर इसे ईमेल पर भेजें: [email protected] हम इसे आपके लिए यथाशीघ्र संभालेंगे।
Copyright© 2022 湘ICP备2022001581号-3