การวิจัยหลักในบทความนี้คือการแพร่กระจายธุรกรรมฤดูใบไม้ผลิและหลักการดำเนินการซึ่งมีการแนะนำดังนี้
Spring ปัจจุบันเป็นมาตรฐานที่แท้จริงสำหรับการพัฒนา Java ด้วยความสะดวกสบายฟังก์ชั่นที่สมบูรณ์และใช้งานง่าย ในระหว่างกระบวนการพัฒนา DB การดำเนินงานเป็นการดำเนินการที่พบบ่อยมากและเมื่อพูดถึง DB มันเกี่ยวข้องกับการทำธุรกรรม ในระหว่างกระบวนการพัฒนาตามปกติของการทำธุรกรรมแม้ว่าคุณจะไม่สังเกตเห็นมันจะไม่มีผลข้างเคียงต่อการดำเนินการตามปกติของโปรแกรม อย่างไรก็ตามหากมีข้อยกเว้นเกิดขึ้นและการทำธุรกรรมไม่ได้รับการจัดการอย่างถูกต้องผลลัพธ์ที่ไม่คาดคิดอาจเกิดขึ้น ฤดูใบไม้ผลิได้ห่อหุ้มการดำเนินงานที่หลากหลายในแง่ของการทำธุรกรรมโดยเฉพาะอย่างยิ่งการเกิดขึ้นของการทำธุรกรรมที่ประกาศทำให้การพัฒนาสะดวกสบายมากขึ้น สปริงขยายธุรกรรมและสนับสนุนคำจำกัดความของคุณลักษณะการแพร่กระจายหลายครั้งซึ่งเป็นจุดสนใจของบทความนี้
ไม่ได้พูดอย่างเคร่งครัดธุรกรรมคือตัวย่อของการดำเนินการหลายอย่าง การดำเนินการเหล่านี้มีผลหรือไม่มีผล (เทียบเท่ากับการไม่ถูกดำเนินการ) กระบวนการดำเนินการทั่วไปง่ายขึ้นดังนี้:
ลอง {connection conn = getConnection (); // ดำเนินการฐานข้อมูลบางอย่าง} catch (Exception e) {conn.rollback ();} ในที่สุด {conn.close ();}ปัญหาบางอย่างสามารถเห็นได้จากรหัสข้างต้น:
ฤดูใบไม้ผลิจัดทำธุรกรรมที่ประกาศออกมาดังนั้นเราไม่ต้องให้ความสนใจกับการใช้งานเฉพาะของเลเยอร์พื้นฐานและบล็อกรายละเอียดการใช้งานที่แตกต่างกันมากมายของเลเยอร์พื้นฐาน เพื่อรองรับการควบคุมการทำธุรกรรมที่ดีโดยธุรกิจที่ซับซ้อนหลายแห่งสปริงให้คุณลักษณะการแพร่กระจายของการทำธุรกรรมและเมื่อรวมกับการทำธุรกรรมที่เปิดเผยมันได้กลายเป็นเครื่องมือการทำธุรกรรมที่สำคัญ
ในคลาส TransactionDefinition สปริงมีคุณสมบัติการแพร่กระจาย 6 รายการซึ่งอธิบายด้วยตัวอย่างง่ายๆ
การเตือนความจำที่อบอุ่น: ต่อไปนี้ที่กล่าวถึงการเข้าร่วมธุรกรรมปัจจุบันหมายถึงการใช้การเชื่อมต่อเดียวกันที่ด้านล่าง แต่วัตถุสถานะการทำธุรกรรมสามารถสร้างขึ้นใหม่และไม่ส่งผลกระทบต่อมัน บทความกล่าวว่ามีการทำธุรกรรมเพียงครั้งเดียวในปัจจุบันซึ่งหมายความว่ามีการแบ่งปันการเชื่อมต่อพื้นฐานและไม่สนใจว่าจะมีการสร้างวัตถุสถานะการทำธุรกรรมจำนวนเท่าใด (ธุรกรรม)
คำอธิบาย: หากมีการทำธุรกรรมอยู่แล้วให้เข้าร่วมการทำธุรกรรม หากไม่มีธุรกรรมให้สร้างธุรกรรม นี่คือค่าแอตทริบิวต์การแพร่กระจายเริ่มต้น
มาดูตัวอย่างเล็ก ๆ น้อย ๆ รหัสมีดังนี้:
@TransactionalPublic Void Service () {ServiceA (); serviceb ();}@transactionalservicea ();@transactionAlserviceB ();Servicea และ ServiceB ทั้งคู่ประกาศธุรกรรม โดยค่าเริ่มต้นการแพร่กระจาย = propagation_required ในระหว่างกระบวนการโทรบริการทั้งหมดมีการทำธุรกรรมที่ใช้ร่วมกันเพียงครั้งเดียว เมื่อมีข้อยกเว้นใด ๆ เกิดขึ้นการดำเนินการทั้งหมดจะถูกย้อนกลับ
คำอธิบาย: หากมีการทำธุรกรรมอยู่แล้วให้เข้าร่วมการทำธุรกรรมมิฉะนั้นจะมีการสร้างธุรกรรมที่ว่างเปล่าที่เรียกว่า (อาจถือได้ว่าไม่มีการดำเนินการธุรกรรม)
มาดูตัวอย่างเล็ก ๆ น้อย ๆ รหัสมีดังนี้:
บริการโมฆะสาธารณะ () {ServiceA (); โยน runtimeException ใหม่ ();}@transactional (การแพร่กระจาย = การแพร่กระจาย. supports) serviceA ();ขณะนี้ไม่มีการทำธุรกรรมเมื่อ ServiceA กำลังดำเนินการดังนั้นข้อยกเว้นที่ถูกโยนลงไปในบริการจะไม่ทำให้ Servicea กลับมาอีกครั้ง
มาดูตัวอย่างเล็ก ๆ อีกตัวอย่างหนึ่งรหัสมีดังนี้:
บริการโมฆะสาธารณะ () {servicea ();}@transactional (การแพร่กระจาย = การแพร่กระจาย. supports) servicea () {ทำ SQL 1 1/0; ทำ SQL 2}เนื่องจาก ServiceA ไม่มีธุรกรรมเมื่อทำงานในเวลานี้หากแหล่งข้อมูลพื้นฐาน defaultAutocommit = TRUE ดังนั้น SQL1 จึงมีประสิทธิภาพ หาก defaultAutocommit = false ดังนั้น SQL1 จะไม่ถูกต้อง หากบริการมีแท็ก @Transactional ServiceA จะแบ่งปันธุรกรรมบริการ (ไม่พึ่งพา defaultAutocommit อีกต่อไป) ในเวลานี้ Servicea ทั้งหมดย้อนกลับไป
คำอธิบาย: การทำธุรกรรมจะต้องมีอยู่ในปัจจุบันมิฉะนั้นจะมีข้อยกเว้น
มาดูตัวอย่างเล็ก ๆ น้อย ๆ รหัสมีดังนี้:
บริการโมฆะสาธารณะ () {ServiceB (); ServiceA ();} ServiceB () {DO SQL} @Transactional (การแพร่กระจาย = การแพร่กระจาย. mandatory) ServiceA () {Do SQL}ในกรณีนี้การดำเนินการบริการจะส่งข้อยกเว้น หาก defaultAutocommit = true serviceb จะไม่ย้อนกลับ หาก defaultAutocommit = false การดำเนินการ ServiceB จะไม่ถูกต้อง
หมายเหตุ: หากมีการทำธุรกรรมในปัจจุบันให้ห่อหุ้มเนื้อหาที่เกี่ยวข้องกับธุรกรรมในปัจจุบันเป็นเอนทิตีจากนั้นสร้างธุรกรรมใหม่ใหม่ยอมรับเอนทิตีนี้เป็นพารามิเตอร์และใช้สำหรับการกู้คืนธุรกรรม คำสั่งทื่อมากขึ้นคือการระงับธุรกรรมปัจจุบัน (ไม่จำเป็นต้องทำธุรกรรม) และสร้างธุรกรรมใหม่ ในกรณีนี้ไม่มีการพึ่งพาระหว่างการทำธุรกรรมทั้งสองและการทำธุรกรรมใหม่สามารถย้อนกลับได้ แต่การทำธุรกรรมภายนอกยังคงดำเนินการต่อไป
มาดูตัวอย่างเล็ก ๆ น้อย ๆ รหัสมีดังนี้:
@TransactionalPublic Void Service () {ServiceB (); ลอง {servicea (); } catch (Exception e) {}} serviceB () {Do SQL} @Transactional (การแพร่กระจาย = การแพร่กระจาย. requires_new) serviceA () {ทำ SQL 1 1/0; ทำ SQL 2}เมื่อเรียกอินเทอร์เฟซบริการเนื่องจาก ServiceA ใช้ต้องการ _New มันจะสร้างธุรกรรมใหม่ อย่างไรก็ตามเนื่องจาก Servicea โยนข้อยกเว้นรันไทม์ Servicea จึงถูกย้อนกลับไป ในวิธีการบริการมีการจับข้อยกเว้นดังนั้น ServiceB จะถูกส่งตามปกติ โปรดทราบว่าการลอง ... รหัสจับในบริการเป็นสิ่งจำเป็นมิฉะนั้นบริการจะโยนข้อยกเว้นทำให้ ServiceB ถูกย้อนกลับ
หมายเหตุ: หากมีการทำธุรกรรมอยู่ในปัจจุบันให้ระงับธุรกรรมปัจจุบันจากนั้นวิธีการใหม่จะถูกดำเนินการในสภาพแวดล้อมโดยไม่มีธุรกรรมและในสภาพแวดล้อมโดยไม่มีธุรกรรมฤดูใบไม้ผลิ
มาดูตัวอย่างเล็ก ๆ น้อย ๆ รหัสมีดังนี้:
@TransactionalPublic Void Service () {ServiceB (); ServiceA ();} ServiceB () {DO SQL} @TransActional (การแพร่กระจาย = การแพร่กระจาย NONT_SUPPORTED) ServiceA () {ทำ SQL 1 1/0; ทำ SQL 2}เมื่อมีการเรียกวิธีการบริการข้อยกเว้นจะถูกโยนลงเมื่อรหัส 1/0 ในวิธีการ ServiceA ถูกดำเนินการ เนื่องจาก ServiceA อยู่ในสภาพแวดล้อมที่ปราศจากธุรกรรมหรือไม่ SQL1 นั้นมีประสิทธิภาพขึ้นอยู่กับค่าของ defaultautocommit หรือไม่ เมื่อ defaultAutocommit = true, SQL1 มีประสิทธิภาพ แต่ ServiceB จะถูกย้อนกลับเพราะบริการจะมีข้อยกเว้น
คำอธิบาย: หากมีการทำธุรกรรมในปัจจุบันข้อยกเว้นจะถูกโยนลงมิฉะนั้นรหัสจะถูกดำเนินการในสภาพแวดล้อมที่ไม่มีธุรกรรม
มาดูตัวอย่างเล็ก ๆ น้อย ๆ รหัสมีดังนี้:
บริการโมฆะสาธารณะ () {ServiceB (); ServiceA ();} ServiceB () {DO SQL} @TransActional (การแพร่กระจาย = การแพร่กระจาย. never) ServiceA () {ทำ SQL 1 1/0; ทำ SQL 2}หลังจากบริการตัวอย่างข้างต้นการเรียกใช้บริการหาก defaultAutocommit = TRUE เมธอด ServiceB และ SQL1 ใน ServiceA จะมีผล
หมายเหตุ: หากมีการทำธุรกรรมอยู่ในปัจจุบันให้ใช้เทคโนโลยี SavePoint เพื่อบันทึกสถานะการทำธุรกรรมปัจจุบันและจากนั้นเลเยอร์พื้นฐานจะแบ่งปันการเชื่อมต่อ เมื่อเกิดข้อผิดพลาดภายในซ้อนกันมันจะย้อนกลับไปยังสถานะ SavePoint ด้วยตัวเอง ตราบใดที่ข้อยกเว้นถูกจับโดยภายนอกก็สามารถทำธุรกรรมภายนอกได้โดยไม่ถูกรบกวนจากธุรกิจที่ฝังตัว อย่างไรก็ตามหากมีข้อยกเว้นถูกโยนทิ้งโดยธุรกรรมภายนอกธุรกรรมขนาดใหญ่ทั้งหมดจะถูกย้อนกลับ
หมายเหตุ: ตัวจัดการธุรกรรมการกำหนดค่าสปริงจะต้องระบุ NestedTransactionAllowed = TRUE ดังที่แสดงด้านล่าง:
<bean id = "dataTransactionManager"> <property name = "dataSource" ref = "dataDataSource" /> <property name = "nestedTransactionallyed" value = "true" /> </ebean>
ดูตัวอย่างเล็ก ๆ รหัสมีดังนี้:
@TransactionalPublic Void Service () {ServiceA (); ลอง {serviceb (); } catch (exception e) {}} serviceA () {ทำ sql} @transactional (การแพร่กระจาย = การแพร่กระจาย. nested) serviceb () {ทำ sql1 1/0; ทำ SQL2}ServiceB เป็นบริการที่ฝังตัวและมีข้อยกเว้นรันไทม์ถูกโยนลงภายในดังนั้น ServiceB จึงถูกย้อนกลับไป เนื่องจากบริการจับข้อยกเว้น ServiceA สามารถส่งได้ตามปกติ
ลองมาดูตัวอย่างอื่นรหัสมีดังนี้:
@TransactionalPublic Void Service () {ServiceA (); ServiceB (); 1/0;}@transactional (การแพร่กระจาย = การเผยแพร่.เนื่องจากบริการมีข้อยกเว้นวิธีการบริการทั้งหมดจะถูกย้อนกลับ (สิ่งนี้แตกต่างจาก Propagation_Requires_New. บริการฝังตัวภายใต้โหมดซ้อนกันจะถูกย้อนกลับโดยมีข้อยกเว้นจากการทำธุรกรรมภายนอก)
ตัวอย่างข้างต้นแสดงให้เห็นถึงคุณลักษณะการแพร่กระจายหลายอย่างที่ได้รับจากการทำธุรกรรมในฤดูใบไม้ผลิใช้เพื่อตอบสนองความต้องการทางธุรกิจที่แตกต่างกันซึ่งสามารถกำหนดได้โดยธุรกิจ จากนั้นมาดูกันว่าการพึ่งพาทางเทคนิคที่สำคัญที่สุดของสปริงใช้คุณลักษณะการแพร่กระจายเหล่านี้อย่างไร ส่วนนี้แสดงรายการ propagation_requires_new และการแพร่กระจายไปแล้วสำหรับคำอธิบายสั้น ๆ ตามลำดับ
การโทรรหัสต่อไปนี้:
@TransactionalPublic Void Service () {ServiceB (); ลอง {servicea (); } catch (exception e) {}}@transactional (การแพร่กระจาย = การแพร่กระจาย. requires_new) serviceA () {ทำ SQL 1 1/0; ทำ sql 2} serviceb () {do sql}แผนผังการดำเนินการมีดังนี้:
. สร้างวัตถุสถานะการทำธุรกรรมรับการเชื่อมต่อใหม่รีเซ็ต autocommit, fetchsize, หมดเวลาและคุณสมบัติอื่น ๆ ของการเชื่อมต่อ
ข. ผูกการเชื่อมต่อกับตัวแปร ThreadLocal
ค. รอการทำธุรกรรมปัจจุบันห่อหุ้มวัตถุสถานะธุรกรรมการเชื่อมต่อและข้อมูลอื่น ๆ ลงในวัตถุที่ถูกระงับซึ่งสามารถใช้สำหรับการกู้คืน
d. สร้างวัตถุสถานะธุรกรรมใหม่ Reacquire การเชื่อมต่อใหม่รีเซ็ต autocommit, fetchsize, หมดเวลาและคุณสมบัติอื่น ๆ ของการเชื่อมต่อใหม่ ในเวลาเดียวกันบันทึกวัตถุ SuspendResources สำหรับการกู้คืนการทำธุรกรรมและผูกการเชื่อมต่อใหม่กับตัวแปร ThreadLocal (Overwrite Operation)
ก. จับข้อยกเว้นย้อนกลับการเชื่อมต่อใน ThreadLocal คืนค่าพารามิเตอร์การเชื่อมต่อปิดการเชื่อมต่อและกู้คืนแหล่งข้อมูลที่ถูกระงับ
f. ส่งการเชื่อมต่อในตัวแปร ThreadLocal (ทำให้ ServiceB ส่ง) คืนค่าพารามิเตอร์การเชื่อมต่อปิดการเชื่อมต่อและส่งคืนการเชื่อมต่อไปยังแหล่งข้อมูล
ดังนั้นผลลัพธ์ของการดำเนินการโปรแกรมคือ ServiceA ถูกย้อนกลับและส่ง ServiceB สำเร็จ
การโทรรหัสต่อไปนี้:
@TransactionalPublic Void Service () {ServiceA (); ลอง {serviceb (); } catch (exception e) {}} serviceA () {ทำ sql} @transactional (การแพร่กระจาย = การแพร่กระจาย. nested) serviceb () {ทำ sql1 1/0; ทำ SQL2}แผนผังการดำเนินการมีดังนี้:
. สร้างวัตถุสถานะการทำธุรกรรมรับการเชื่อมต่อใหม่รีเซ็ต autocommit, fetchsize, หมดเวลาและคุณสมบัติอื่น ๆ ของการเชื่อมต่อ
ข. ผูกการเชื่อมต่อกับตัวแปร ThreadLocal
ค. ทำเครื่องหมายการใช้วัตถุสถานะธุรกรรมปัจจุบันรับวัตถุการเชื่อมต่อ ThreadLocal, บันทึก SavePoint ของการเชื่อมต่อปัจจุบันและใช้สำหรับการกู้คืนข้อยกเว้น ในเวลานี้ SavePoint เป็นสถานะหลังจาก ServiceA ถูกดำเนินการ
d. จับข้อยกเว้นและใช้ SavePoint ใน C สำหรับการทำธุรกรรมย้อนกลับนั่นคือย้อนกลับสถานะกลับสู่สถานะหลังจากดำเนินการ ServiceA การประหารชีวิตทั้งหมดของวิธีการ ServiceB ไม่มีผลบังคับใช้
ก. รับวัตถุการเชื่อมต่อใน ThreadLocal, ส่งธุรกรรม, กู้คืนคุณสมบัติการเชื่อมต่อ, การเชื่อมต่อปิด
จากแหล่งข้อมูลพื้นฐาน Spring ใช้ ThreadLocal, SavePoint และจุดทางเทคนิคอื่น ๆ เพื่อให้ตระหนักถึงคุณลักษณะการแพร่กระจายการทำธุรกรรมที่หลากหลายซึ่งอำนวยความสะดวกในการใช้บริการที่ซับซ้อนต่างๆ โดยการทำความเข้าใจหลักการของคุณลักษณะการแพร่กระจายเท่านั้นที่เราสามารถควบคุมการทำธุรกรรมสปริงได้ดีขึ้น ธุรกรรมการย้อนกลับของฤดูใบไม้ผลิขึ้นอยู่กับการจับข้อยกเว้น โดยค่าเริ่มต้นการทำธุรกรรมจะถูกย้อนกลับไปหาก RuntimeException และข้อผิดพลาดถูกโยนทิ้ง แน่นอนมันสามารถกำหนดค่าได้ สำหรับข้อมูลเพิ่มเติมคุณสามารถตรวจสอบคำอธิบายประกอบ @Transactional
การทำธุรกรรมที่ประกาศของฤดูใบไม้ผลิทำให้เราสะดวกสบาย เพื่อใช้ประโยชน์จากอาวุธนี้เป็นอย่างดีมันยังจำเป็นที่จะต้องเข้าใจหลักการพื้นฐาน บทความนี้เป็นเพียงส่วนเล็ก ๆ ของภูเขาน้ำแข็งของการทำธุรกรรมฤดูใบไม้ผลิ ผู้อ่านสามารถสำรวจในเชิงลึกบนพื้นฐานนี้
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้เกี่ยวกับการเผยแพร่ธุรกรรมฤดูใบไม้ผลิและหลักการดำเนินการ ฉันหวังว่ามันจะเป็นประโยชน์กับทุกคน เพื่อนที่สนใจสามารถอ้างถึงหัวข้ออื่น ๆ ที่เกี่ยวข้องในเว็บไซต์นี้ต่อไป หากมีข้อบกพร่องใด ๆ โปรดฝากข้อความไว้เพื่อชี้ให้เห็น ขอบคุณเพื่อนที่ให้การสนับสนุนเว็บไซต์นี้!