การทำธุรกรรม Java มีสามประเภท: ธุรกรรม JDBC, การทำธุรกรรม JTA (การทำธุรกรรม Java API) และธุรกรรมคอนเทนเนอร์ ธุรกรรมคอนเทนเนอร์ทั่วไปเช่นธุรกรรมสปริง ธุรกรรมคอนเทนเนอร์ส่วนใหญ่จัดทำโดยเซิร์ฟเวอร์แอปพลิเคชัน J2EE ธุรกรรมคอนเทนเนอร์ส่วนใหญ่เสร็จสมบูรณ์ตาม JTA นี่คือการใช้งาน API ที่ใช้ JNDI ค่อนข้างซับซ้อน ดังนั้นบทความนี้จะไม่หารือเกี่ยวกับการทำธุรกรรมคอนเทนเนอร์ในขณะนี้ บทความนี้ส่วนใหญ่แนะนำสองธุรกรรมพื้นฐานที่ค่อนข้างพื้นฐานในการพัฒนา J2EE: ธุรกรรม JDBC และธุรกรรม JTA
ธุรกรรม JDBC
พฤติกรรมทั้งหมดรวมถึงการทำธุรกรรมของ JDBC ขึ้นอยู่กับการเชื่อมต่อและการจัดการธุรกรรมจะดำเนินการผ่านวัตถุการเชื่อมต่อใน JDBC ใน JDBC วิธีการที่เกี่ยวข้องกับธุรกรรมที่ใช้กันทั่วไปคือ: setautocommit, commit, rellback ฯลฯ
นี่คือรหัสธุรกรรม JDBC อย่างง่าย:
โมฆะสาธารณะ jdbctransfer () {java.sql.connection conn = null; ลอง {conn = conn = driverManager.getConnection ("JDBC: Oracle: Thin: @Host: 1521: SID", "ชื่อผู้ใช้", "userpwd"); // ตั้งค่าการยอมรับอัตโนมัติเป็นเท็จ // ถ้าตั้งค่าเป็นจริงฐานข้อมูลจะรับรู้การอัปเดตข้อมูลแต่ละครั้งเป็นธุรกรรมและส่ง conn.setautocommit โดยอัตโนมัติ (เท็จ); stmt = conn.createstatement (); // ลดจำนวนเงินในบัญชี A 500 STMT.Execute ("/ UPDATE T_ACCOUNT SET จำนวนเงิน = จำนวน - 500 โดยที่ Account_ID = 'A'"); // เพิ่มจำนวนเงินในบัญชี b 500 stmt.execute ("/ อัปเดต t_account ชุดจำนวน = จำนวน + 500 โดยที่บัญชี _id = 'b'"); // ส่งธุรกรรม conn.commit (); // การทำธุรกรรม commit: การดำเนินการสองขั้นตอนของการถ่ายโอนประสบความสำเร็จในเวลาเดียวกัน} catch (sqlexception sqle) {ลอง {// ข้อยกเว้นเกิดขึ้น, ย้อนกลับ () ในธุรกรรมนี้ conn.rollback (); // การย้อนกลับธุรกรรม: การดำเนินการสองขั้นตอนของการถ่ายโอนเพิกถอน Stmt.Close () อย่างสมบูรณ์; conn.close (); } catch (ข้อยกเว้นละเว้น) {} sqle.printstacktrace (); -รหัสข้างต้นใช้ฟังก์ชันการถ่ายโอนอย่างง่ายซึ่งควบคุมการถ่ายโอนผ่านธุรกรรมไม่ว่าจะเป็นการส่งหรือย้อนกลับ
ข้อดีและข้อเสียของการทำธุรกรรม JDBC
JDBC ให้การสนับสนุนพื้นฐานที่สุดสำหรับการดำเนินการทำธุรกรรมฐานข้อมูลโดยใช้ Java ผ่านการทำธุรกรรม JDBC เราสามารถใส่คำสั่ง SQL หลายรายการลงในธุรกรรมเดียวกันเพื่อให้แน่ใจว่ามีลักษณะของกรด ข้อได้เปรียบหลักของการทำธุรกรรม JDBC คือ API นั้นค่อนข้างง่ายสามารถใช้การดำเนินการธุรกรรมขั้นพื้นฐานที่สุดและประสิทธิภาพค่อนข้างดี
อย่างไรก็ตามธุรกรรม JDBC มีข้อ จำกัด หนึ่งข้อ: ธุรกรรม JDBC ไม่สามารถขยายฐานข้อมูลได้หลายฐาน! - - ดังนั้นหากการดำเนินการฐานข้อมูลหลายครั้งหรือสถานการณ์แบบกระจายมีส่วนเกี่ยวข้องการทำธุรกรรม JDBC นั้นไม่มีอำนาจ
ธุรกรรม JTA
ทำไมต้องใช้ JTA
โดยปกติการทำธุรกรรม JDBC สามารถแก้ปัญหาเช่นความสอดคล้องของข้อมูล เนื่องจากการใช้งานนั้นค่อนข้างง่ายหลายคนรู้ว่ามีธุรกรรม JDBC เกี่ยวกับการทำธุรกรรมใน Java หรือบางคนรู้เกี่ยวกับการทำธุรกรรมในกรอบ (เช่น Hibernate, Spring) ฯลฯ เนื่องจาก JTA ไม่สามารถใช้การทำธุรกรรมแบบกระจาย
หากคุณไม่พบสถานการณ์ที่การทำธุรกรรม JDBC ไม่สามารถแก้ไขได้ในที่ทำงานคุณสามารถพูดได้ว่าโครงการที่คุณทำนั้นยังเล็กเกินไป นำเว็บไซต์อีคอมเมิร์ซเป็นตัวอย่าง โดยทั่วไปเราแบ่งเว็บไซต์อีคอมเมิร์ซในแนวนอนเป็นโมดูลผลิตภัณฑ์โมดูลคำสั่งซื้อโมดูลตะกร้าสินค้าโมดูลข้อความโมดูลการชำระเงิน ฯลฯ จากนั้นเราปรับใช้โมดูลที่แตกต่างกันกับเครื่องจักรที่แตกต่างกันและแต่ละโมดูลสื่อสารผ่านการโทรระยะไกล (RPCs) และวิธีการอื่น ๆ ให้บริการแก่โลกภายนอกด้วยระบบกระจาย
กระบวนการชำระเงินจะต้องโต้ตอบกับหลายโมดูลแต่ละโมดูลจะถูกปรับใช้ในเครื่องที่แตกต่างกันและฐานข้อมูลที่ดำเนินการโดยแต่ละโมดูลนั้นไม่สอดคล้องกัน ในเวลานี้ JDBC ไม่สามารถใช้ในการจัดการธุรกรรม มาดูรหัสชิ้นหนึ่ง:
/ ** การประมวลผลคำสั่งการชำระเงิน **/ @TransActional (rollbackfor = exception.class) โมฆะสาธารณะสมบูรณ์ () {orderdao.update (); // คำสั่งซื้อบริการอัปเดตสถานะการสั่งซื้อบัญชี accountService.update (); // โทรหาบริการบัญชีกองทุนเพื่อเพิ่มคะแนนไปยังบัญชีกองทุน Pointservice.update (); // โทรหาบริการคะแนนเพื่อเพิ่มคะแนนไปยังบัญชีบัญชีบัญชีบัญชี Accateingservice.Insert (); // โทรหาบริการบัญชีเพื่อเขียนระบบบัญชีบัตรกำนัลบัญชีดั้งเดิม MerchantNotIfyService.Notify (); // โทรหาบริการแจ้งเตือนผู้ค้าเพื่อส่งการแจ้งเตือนการชำระเงินไปยังผู้ค้า}รหัสข้างต้นเป็นการดำเนินการขั้นตอนการชำระเงินอย่างง่ายซึ่งมีการเรียกใช้บริการห้ารายการซึ่งทั้งหมดนี้เรียกผ่าน RPC จะมั่นใจได้อย่างไรว่าการทำธุรกรรมนั้นสอดคล้องกันโดยใช้ JDBC ฉันเพิ่มคำอธิบายประกอบ @Transactional ลงในวิธีการ แต่เนื่องจากการใช้บริการแบบกระจายการทำธุรกรรมไม่สามารถบรรลุผลของกรดได้
ธุรกรรม JTA นั้นมีประสิทธิภาพมากกว่าธุรกรรม JDBC ธุรกรรม JTA สามารถมีผู้เข้าร่วมหลายคนในขณะที่ธุรกรรม JDBC ถูก จำกัด ไว้ที่การเชื่อมต่อฐานข้อมูลเดียว ส่วนประกอบของแพลตฟอร์ม Java ใด ๆ ต่อไปนี้สามารถเข้าร่วมในการทำธุรกรรม JTA: การเชื่อมต่อ JDBC, JDO PresentenceManager Object, JMS Queue, JMS หัวข้อ, J2EE, J2EE JABABEANS (EJB)
คำจำกัดความของ JTA
Java Transaction API (JTA) เป็นอินเตอร์เฟสโปรแกรมแอปพลิเคชัน Java Enterprise ในสภาพแวดล้อม Java จะช่วยให้การทำธุรกรรมแบบกระจายผ่านทรัพยากร XA หลายรายการจะเสร็จสมบูรณ์
JTA และบริการธุรกรรม Java ร่วมกัน (JTS; Java TransactionService) ให้บริการธุรกรรมแบบกระจายสำหรับแพลตฟอร์ม J2EE อย่างไรก็ตาม JTA จัดเตรียมอินเทอร์เฟซเท่านั้นและไม่ได้ให้การใช้งานเฉพาะ แต่ให้บริการโดยผู้ให้บริการเซิร์ฟเวอร์ J2EE ตามข้อกำหนดของ JTS มีการใช้งาน JTA ทั่วไปหลายประการ:
1. การใช้งาน JTA (JBOSS) จัดทำโดย J2EE Container
2. การใช้งาน JTA อิสระ: เช่น JOTM, Atomikos การใช้งานเหล่านี้สามารถใช้ในสภาพแวดล้อมที่ไม่ใช้เซิร์ฟเวอร์แอปพลิเคชัน J2EE เพื่อให้การรับประกันการทำธุรกรรมแบบกระจาย เช่นแอปพลิเคชัน Java Java และ Java ธรรมดา
JTA จัดเตรียม java.transaction.userTransaction ซึ่งกำหนดวิธีการต่อไปนี้
ที่นี่เป็นที่น่าสังเกตว่าการดำเนินการ JDBC ธรรมดาสามารถแปลงโดยตรงเป็นการดำเนินการ JTA ได้โดยตรงโดยไม่ต้องใช้ userTransAction JTA มีข้อกำหนดสำหรับแหล่งข้อมูลการเชื่อมต่อและทรัพยากร เฉพาะคลาสที่สอดคล้องกับข้อกำหนด XA และใช้อินเทอร์เฟซที่เกี่ยวข้องของข้อกำหนด XA เท่านั้นที่สามารถเข้าร่วมในธุรกรรม JTA ได้ เกี่ยวกับข้อกำหนด XA โปรดดูการแนะนำที่เกี่ยวข้องในบทความอื่นในบทความของฉัน ที่นี่ให้ฉันพูดถึงฐานข้อมูลกระแสหลักปัจจุบันรองรับข้อมูลจำเพาะ XA
ในการใช้ธุรกรรม JTA คุณต้องใช้ไดรเวอร์ JDBC ที่ใช้ Javax.sql.xadatasource, javax.sql.xaconnection และ Javax.sql.xaresource อินเทอร์เฟซ ไดรเวอร์ที่ใช้อินเทอร์เฟซเหล่านี้จะสามารถเข้าร่วมในธุรกรรม JTA ได้ วัตถุ Xadatasource เป็นโรงงานของวัตถุ Xaconnection Xaconnection เป็นการเชื่อมต่อ JDBC ที่เข้าร่วมในการทำธุรกรรม JTA
ในการใช้ธุรกรรม JTA คุณต้องใช้ Xadatasource เพื่อสร้างการเชื่อมต่อฐานข้อมูลและการเชื่อมต่อที่เกิดขึ้นคือการเชื่อมต่อ XA
ความแตกต่างระหว่างการเชื่อมต่อ XA (javax.sql.xaconnection) และการเชื่อมต่อที่ไม่ใช่ XA (java.sql.Connection) คือ XA สามารถเข้าร่วมในการทำธุรกรรม JTA และไม่สนับสนุนการกระทำอัตโนมัติ
รหัสตัวอย่าง:
โมฆะสาธารณะ jtatransfer () {javax.transaction.userTransaction tx = null; java.sql.connection conn = null; ลอง {tx = (javax.transaction.userTransaction) Context.lookup ("Java: comp/userTransaction"); // รับธุรกรรม JTA ในกรณีนี้คอนเทนเนอร์ JBoss ได้รับการจัดการโดย javax.sql.datasource ds = (javax.sql.datasource) บริบท lookup ("java:/xaoracleds"); // รับพูลการเชื่อมต่อฐานข้อมูลจะต้องมีฐานข้อมูลและไดรเวอร์ที่รองรับ XA ที่รองรับ tx.begin (); conn = ds.getConnection (); // ตั้งค่าการยอมรับอัตโนมัติเป็นเท็จ // ถ้าตั้งค่าเป็นจริงฐานข้อมูลจะรับรู้การอัปเดตข้อมูลแต่ละครั้งเป็นธุรกรรมและส่ง conn.setautocommit โดยอัตโนมัติ (เท็จ); stmt = conn.createstatement (); // ลดจำนวนเงินในบัญชี A 500 STMT.Execute ("/ UPDATE T_ACCOUNT SET จำนวนเงิน = จำนวน - 500 โดยที่ Account_ID = 'A'"); // เพิ่มจำนวนเงินในบัญชี b 500 stmt.execute ("/ อัปเดต t_account ชุดจำนวน = จำนวน + 500 โดยที่บัญชี _id = 'b'"); // เพิ่มจำนวนเงินในบัญชี b 500 stmt.execute ("/ อัปเดต t_account ชุดจำนวน = จำนวน + 500 โดยที่บัญชี _id = 'b'"); // เพิ่มจำนวนเงินในบัญชี b 500 stmt.execute ("/ อัปเดต t_account ชุดจำนวน = จำนวน + 500 โดยที่บัญชี _id = 'b'"); // กระทำการทำธุรกรรม tx.commit (); // การทำธุรกรรม commit: การดำเนินการสองขั้นตอนของการถ่ายโอนจะประสบความสำเร็จในเวลาเดียวกัน} catch (sqlexception sqle) {ลอง {// มีข้อยกเว้นเกิดขึ้น, ย้อนกลับ () ในการทำธุรกรรมนี้; // การย้อนกลับธุรกรรม: การดำเนินการสองขั้นตอนของการถ่ายโอนจะถูกเพิกถอนอย่างสมบูรณ์ stmt.close (); conn.close (); } catch (ข้อยกเว้นละเว้น) {} sqle.printstacktrace (); - ตัวอย่างข้างต้นคือการถ่ายโอนโดยใช้ธุรกรรม JTA การดำเนินการนี้ค่อนข้างขึ้นอยู่กับคอนเทนเนอร์ J2EE และต้องใช้การสร้าง userTransAction และการเชื่อมต่อที่จะได้รับผ่าน JNDI
ธุรกรรมแบบกระจายมาตรฐาน
ธุรกรรมแบบกระจายรวมถึงผู้จัดการธุรกรรมและผู้จัดการทรัพยากรอย่างน้อยหนึ่งตัว ตัวจัดการทรัพยากรเป็นที่เก็บข้อมูลแบบถาวรทุกประเภท ผู้จัดการธุรกรรมจะรับผิดชอบในการสื่อสารระหว่างผู้เข้าร่วมการทำธุรกรรมทั้งหมด
ดูการแนะนำด้านข้างต้นเกี่ยวกับการทำธุรกรรมแบบกระจายมันคล้ายกับการจัดการธุรกรรมใน 2pc หรือไม่? อย่างไรก็ตาม 2PC เป็นวิธีการใช้งานสำหรับตัวจัดการธุรกรรมที่สอดคล้องกับข้อกำหนด XA เพื่อประสานงานผู้จัดการทรัพยากรหลายตัว ฉันเคยมีบทความหลายเรื่องเกี่ยวกับ 2pc และ 3pc มาก่อน ในบทความเหล่านั้นฉันได้แนะนำวิธีการผู้จัดการธุรกรรมในการทำธุรกรรมแบบกระจายประสานงานการกระทำแบบครบวงจรหรือย้อนกลับของการทำธุรกรรมหลายรายการ ฉันจะแนะนำรายละเอียดเกี่ยวกับเนื้อหาที่เกี่ยวข้องกับการทำธุรกรรมแบบกระจายรวมถึง แต่ไม่ จำกัด เพียงการทำธุรกรรมทั่วโลก, โมเดล DTP, ธุรกรรมที่ยืดหยุ่น ฯลฯ
ข้อดีและข้อเสียของ JTA
ข้อได้เปรียบของ JTA คือให้วิธีการทำธุรกรรมแบบกระจายและกรดที่เข้มงวด อย่างไรก็ตามการจัดการธุรกรรม JTA มาตรฐานไม่ได้ใช้กันทั่วไปในการพัฒนาทุกวันเนื่องจากมีข้อบกพร่องมากมาย:
คอมเพล็กซ์การใช้งาน
โดยปกติจะต้องได้รับ JTA userTransaction จาก JNDI ซึ่งหมายความว่าถ้าเราใช้ JTA เราต้องใช้ทั้ง JTA และ JNDI
JTA เองเป็น API ขนาดใหญ่
โดยปกติแล้ว JTA สามารถใช้งานได้ในสภาพแวดล้อมแอปพลิเคชันเซิร์ฟเวอร์เท่านั้นดังนั้นการใช้ JTA จะ จำกัด การใช้รหัสใหม่
สรุป
การทำธุรกรรม Java มีสามประเภท: ธุรกรรม JDBC, การทำธุรกรรม JTA (การทำธุรกรรม Java API) และธุรกรรมคอนเทนเนอร์ ในหมู่พวกเขาการใช้การทำธุรกรรมของ JDBC นั้นค่อนข้างง่ายและเหมาะสำหรับการจัดการการดำเนินการของแหล่งข้อมูลเดียวกัน ธุรกรรม JTA ค่อนข้างซับซ้อนและสามารถใช้ในการจัดการธุรกรรมในหลายฐานข้อมูล พวกเขาเป็นทางออกสำหรับการทำธุรกรรมแบบกระจาย
ให้ฉันพูดสั้น ๆ เกี่ยวกับที่นี่ แม้ว่าธุรกรรม JTA เป็นชุดของ APIs ที่จัดทำโดย Java สำหรับการทำธุรกรรมแบบกระจาย แต่แพลตฟอร์ม J2EE ที่แตกต่างกันมีการใช้งานที่แตกต่างกันและไม่สะดวกในการใช้งาน ดังนั้น API ที่รับผิดชอบมากขึ้นนี้จึงไม่ได้ใช้ในโครงการ โซลูชันการทำธุรกรรมแบบกระจายที่ใช้กันทั่วไปในอุตสาหกรรมตอนนี้รวมถึงการประกันข้อความแบบอะซิงโครนัส, TCC, การแจ้งเตือนความพยายามสูงสุด ฯลฯ
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่ามันจะเป็นประโยชน์ต่อการเรียนรู้ของทุกคนและฉันหวังว่าทุกคนจะสนับสนุน wulin.com มากขึ้น