คำนำ
ที่อยู่ดาวน์โหลดของรหัสตัวอย่างสำหรับบทความนี้ (ทำงานอย่างสมบูรณ์รวมถึงไฟล์ SQL โปรดแก้ไขการกำหนดค่าฐานข้อมูลหลังจากดาวน์โหลด): คลิกที่นี่เพื่อดาวน์โหลด
การดำเนินการฐานข้อมูลหลายอย่างถูกควบคุมโดยรวมและพวกเขาประสบความสำเร็จหรือล้มเหลวด้วยกัน
Atomicity: หมายถึงการทำธุรกรรมที่เป็นหน่วยงานที่แยกกันไม่ออกและการดำเนินการในการทำธุรกรรมอาจเกิดขึ้นหรือไม่เกิดขึ้น
ความสอดคล้อง: หมายความว่าความสมบูรณ์ของข้อมูลก่อนและหลังการทำธุรกรรมจะต้องสอดคล้องกัน
การแยก: เมื่อผู้ใช้หลายคนเข้าถึงฐานข้อมูลพร้อมกันการทำธุรกรรมของผู้ใช้รายหนึ่งไม่สามารถแทรกแซงการทำธุรกรรมของผู้ใช้รายอื่นและข้อมูลระหว่างการทำธุรกรรมหลายรายการพร้อมกันจะต้องแยกจากกัน
การคงอยู่: เมื่อมีการทำธุรกรรมการเปลี่ยนแปลงข้อมูลในฐานข้อมูลจะถาวรและความล้มเหลวของฐานข้อมูลทันทีไม่ควรมีผลกระทบใด ๆ
-Platform TransactionManager Transaction Manager (commit, transactions ย้อนกลับ)
ฤดูใบไม้ผลิให้การใช้งานอินเทอร์เฟซ TransactionManager แพลตฟอร์มที่แตกต่างกันสำหรับกรอบการคงอยู่ที่แตกต่างกัน ชอบ:
การใช้ DataSourceTransactionManager เมื่อคงข้อมูลโดยใช้ Spring JDBC หรือ Ibatis
ใช้ hibernatetransactionmanager เมื่อใช้ hibernate3.0 สำหรับข้อมูลถาวร
-ข้อมูลนิยามการทำธุรกรรมของ TransactionDefinition (การแยกการแพร่กระจายการหมดเวลาการอ่านอย่างเดียว)
Dirty Reading: ธุรกรรมหนึ่งอ่านข้อมูลที่ได้รับการเขียนใหม่โดยธุรกรรมอื่น แต่ยังไม่ได้ส่ง หากข้อมูลนี้ถูกย้อนกลับไปข้อมูลอ่านจะไม่ถูกต้อง
ไม่มีการอ่านซ้ำ ๆ : ในการทำธุรกรรมเดียวกันผลลัพธ์ที่ส่งคืนโดยการอ่านข้อมูลเดียวกันหลายครั้งจะแตกต่างกัน
การอ่านแฟนตาซี: หลังจากการทำธุรกรรมหนึ่งอ่านบันทึกหลายบรรทัดการทำธุรกรรมอื่นแทรกบันทึกบางอย่างและการอ่านแฟนตาซีเกิดขึ้น ในแบบสอบถามในภายหลังการทำธุรกรรมครั้งแรกจะพบบันทึกบางอย่างที่ไม่ได้มีอยู่เดิม
ระดับการแยกธุรกรรม: (ห้าประเภท)
ในหมู่พวกเขา MySQL ใช้ระดับการแยกซ้ำ repeable_read โดยค่าเริ่มต้น; Oracle ใช้ระดับการแยก read_committed โดยค่าเริ่มต้น
พฤติกรรมการสื่อสารการทำธุรกรรม: (เจ็ดประเภท)
-สถานะการดำเนินการเฉพาะของธุรกรรมการทำธุรกรรม
. การจัดการธุรกรรมการเขียนโปรแกรม (ขึ้นอยู่กับการควบคุมการเขียนโปรแกรม Java ไม่ค่อยได้ใช้)-ดูแพ็คเกจ Demo1
ใช้ TransactionTemplate เพื่อห่อหุ้มการดำเนินการ DAO หลายรายการ
*b. การจัดการธุรกรรมที่ประกาศ (การควบคุมการกำหนดค่า AOP ที่ใช้สปริง)
- ขึ้นอยู่กับ TransactionProxyFactoryBean (ใช้ไม่ค่อยใช้)-ดูแพ็คเกจ Demo2
มีความจำเป็นต้องกำหนดค่า TransactionProxyFactoryBean สำหรับแต่ละคลาสที่อยู่ระหว่างการจัดการธุรกรรมเพื่อการปรับปรุง
-ตามการกำหนดค่า XML (ใช้บ่อย)-ดูแพ็คเกจ Demo3
เมื่อกำหนดค่าแล้วไม่จำเป็นต้องเพิ่มในชั้นเรียน
หากการดำเนินการเป็นวัตถุเป้าหมายในการเข้าสู่ธุรกรรมคุณจะต้องเพิ่มแอตทริบิวต์พร็อกซี-เป้าหมาย-คลาส = "จริง" แอตทริบิวต์ลงในองค์ประกอบ <AOP: config> เหตุผลคือการแจ้งให้ทราบถึง Framework Spring ให้ใช้เทคโนโลยี CGLIB เพื่อสร้างคลาสแอ็คชั่นด้วยฟังก์ชั่นการจัดการธุรกรรม
-ใช้คำอธิบายประกอบ (การกำหนดค่าอย่างง่ายมักใช้)-ดูแพ็คเกจ Demo4
เปิดใช้งานการกำหนดค่าคำอธิบายประกอบการทำธุรกรรมใน ApplicationContext.xml (ใน ApplicationContext.xml เพียงกำหนดถั่วและผนวกองค์ประกอบต่อไปนี้)
<bean id = "txManager"> <property name = "SessionFactory"> </property> <tx: transaction-driven transaction-manager = "txManager"/>
ใช้ @Transactional ในคลาสส่วนประกอบเป้าหมายซึ่งสามารถกำหนดได้ก่อนชั้นเรียนหรือก่อนวิธีการ
-การเขียนโปรแกรม
/ *** @description: อินเทอร์เฟซเลเยอร์ Dao ของกรณีการถ่ายโอน**/ ส่วนต่อประสานสาธารณะบัญชี dao {/ *** @param out*: บัญชีโอน* @param เงิน*: จำนวนเงินโอน*/ โมฆะสาธารณะ / ** * * @param ใน *: โอนบัญชี * @param เงิน *: การโอนจำนวนเงิน */ โมฆะสาธารณะ inmoney (สตริงใน, เงินสองเท่า); - / *** @description: คลาสการใช้งาน Dao Layer ของกรณีการถ่ายโอน*/ Class Public Class AccountDaoImpl ขยาย JDBCDAOSUPPORT ใช้บัญชี {/ *** @param out*: โอนเงิน* @param เงิน*: การโอนเงิน*/ @Override this.getjdbctemplate (). อัปเดต (SQL, เงิน, out); } / *** @param ใน*: การโอนบัญชี* @param เงิน*: โอนจำนวนเงิน* / @Override โมฆะสาธารณะ INMONEY (String in, เงินสองครั้ง) {String SQL = "อัปเดตบัญชี Set Money = Money+? name =?"; this.getjdbctemplate (). อัปเดต (sql, money, in); - / *** @description: อินเทอร์เฟซธุรกิจของกรณีการถ่ายโอน**/ บัญชีสาธารณะบัญชี {/ *** @param out: โอนออก* @param ใน: การโอนบัญชี* @param เงิน: จำนวนเงินโอน*/ โมฆะสาธารณะโอน (สตริง, สตริง, เงินสองครั้ง); - / *** @description: คลาสการใช้งานเลเยอร์ธุรกิจของกรณีการถ่ายโอน*/ บัญชีสาธารณะ accountserviceimpl ดำเนินการบัญชี {// dao private accountdao accountdao; // เทมเพลตสำหรับการฉีดธุรกรรมการทำธุรกรรมส่วนตัว TransactionTemplate TransactionTemplate; / ** * @param out *: โอนออก * @param ใน *: โอนบัญชี * @param เงิน *: จำนวนเงินโอน */ @Override โมฆะสาธารณะการโอน (สตริงสุดท้ายออก, สตริงสุดท้ายใน, เงินสองครั้งสุดท้าย) {// หากมีข้อยกเว้นเกิดขึ้นในระหว่างกระบวนการการดำเนินการก่อนหน้านี้จะเสร็จสิ้น หากหลังไม่สามารถถ่ายโอนได้สำเร็จ แต่ไม่ได้รับการถ่ายโอน // accountdao.outmoney (ออก, เงิน); // int i = 1/0; // accountdao.inmoney (ใน, เงิน); TransactionTemplate.execute (TransactionCallbackWithoutresult () {@Override void doinTransactionWithoutresult (transactionstatus transactionstatus) {accountdao.outmoney (ออก, เงิน); // int i = 1/0; เงิน); } }); } โมฆะสาธารณะ setAccountdao (บัญชี daccountdao) {this.accountdao = accountdao; } โมฆะสาธารณะ setTransactionTemplate (ธุรกรรม Transactiontate TransactionTemplate) {this.TransactionTemplate = TransactionTemplate; -ApplicationContext1.xml
<!-แนะนำไฟล์อสังหาริมทรัพย์ภายนอก-> <บริบท: สถานที่ตั้งสถานที่ตั้งสถานที่ = "classpath: jdbc.properties" /> <!-กำหนดค่าพูลการเชื่อมต่อ C3P0-> <bean id = "dataSource"> <property name = "driverclass" value = "{jdbc.dridclass}" <property name = "user" value = "$ {jdbc.username}" /> <property name = "รหัสผ่าน" value = "$ {jdbc.password}" /> </ebean> <! name = "transactionTemplate" ref = "transactionTemplate" /> </ebean> <!-กำหนดค่าคลาส DAO (ง่าย JDBCTEMPLATE จะได้รับการกำหนดค่าโดยอัตโนมัติ)-> <Bean ID = "AccountDao"> <property name = "dataSource" ref = "dataSource" /> id = "jdbctemplate"> <property name = "dataSource" ref = "dataSource" /> </epean> <bean id = "accountDao"> <property name = "jdbctemplate" ref = "jdbctemplate" /> </ebean>-> <! - - - - กำหนดค่าเทมเพลตการจัดการธุรกรรม: คลาสที่จัดทำโดยฤดูใบไม้ผลิเพื่อลดความซับซ้อนของรหัสการจัดการธุรกรรม -> <bean id = "transactionTemplate"> <ชื่อคุณสมบัติ = "transactionManager" ref = "transactionManager"/> </ebean>ทดสอบ:
@runwith (springjunit4classrunner.class) @contextconfiguration ("classpath: applicationcontext1.xml") การทำธุรกรรมคลาสสาธารณะ transactiontest {@Resource (name = "accountService") บัญชีส่วนตัว @Test โมฆะสาธารณะ demo1 () {accountService.transfer ("AAA", "BBB", 200d); --วิธีที่ใช้ TransactionProxyFactoryBean
AccountServiceImpl บัญชีสาธารณะใช้งานบัญชี {// DAO Private AccountDao AccountDao; / ** * @param out *: โอนออก * @param ใน *: โอนบัญชี * @param เงิน *: การโอนจำนวนเงิน */ @Override โมฆะสาธารณะโอนเงิน (สตริงออก, สตริง, เงินสองครั้ง) {accountdao.outmoney (ออก, เงิน); // int i = 1/0; AccountDao.inmoney (เป็นเงิน); } โมฆะสาธารณะ setAccountdao (บัญชี daccountdao) {this.accountdao = accountdao; -ApplicationContext2.xml
<!-แนะนำไฟล์อสังหาริมทรัพย์ภายนอก-> <บริบท: สถานที่ตั้งสถานที่ตั้งสถานที่ = "classpath: jdbc.properties" /> <!-กำหนดค่าพูลการเชื่อมต่อ C3P0-> <bean id = "dataSource"> <property name = "driverclass" value = "{jdbc.dridclass}" <property name = "user" value = "$ {jdbc.username}" /> <property name = "รหัสผ่าน" value = "$ {jdbc.password}" /> </ebean> <! กำหนดค่า jdbctemplate โดยอัตโนมัติ)-> <bean id = "accountdao"> <property name = "dataSource" ref = "DataSource" /> </ebean> <!-! - - - - -> <!-กำหนดค่าตัวจัดการธุรกรรม-> <bean id = "transactionManager"> <property name = "dataSource" ref = "dataSource" /> </ebean> <!-กำหนดค่าพร็อกซีสำหรับเลเยอร์ธุรกิจ-> <property name = "transactionManager" ref = "transactionManager"> </property> <!-คุณสมบัติการทำธุรกรรมการฉีด-> <property name = "TransactionAttributes"> <props> <! <prop key = "transfer"> propagation_required </prop> <!-<prop key = "transfer"> propagation_required, readonly </prop>-> <!-<prop key = "transfer"> propagation_required, readonly </prop>-> <! </props> </property> </ebean>ทดสอบ:
@runwith (springjunit4classrunner.class) @contextconfiguration ("classpath: applicationcontext2.xml") การทำธุรกรรมระดับสาธารณะ transactiontest { / *** อย่าลืมฉีดคลาสพร็อกซี: proxy class บริการบัญชี; @Test โมฆะสาธารณะ demo1 () {accountService.transfer ("AAA", "BBB", 200d); --อิงตามการกำหนดค่า XML
AccountServiceImpl บัญชีสาธารณะใช้งานบัญชี {// DAO Private AccountDao AccountDao; / ** * @param out *: โอนออก * @param ใน *: โอนบัญชี * @param เงิน *: การโอนจำนวนเงิน */ @Override โมฆะสาธารณะโอนเงิน (สตริงออก, สตริง, เงินสองครั้ง) {accountdao.outmoney (ออก, เงิน); // int i = 1/0; AccountDao.inmoney (เป็นเงิน); } โมฆะสาธารณะ setAccountdao (บัญชี daccountdao) {this.accountdao = accountdao; -ApplicationContext3.xml
<!-แนะนำไฟล์อสังหาริมทรัพย์ภายนอก-> <บริบท: สถานที่ตั้งสถานที่ตั้งสถานที่ = "classpath: jdbc.properties" /> <!-กำหนดค่าพูลการเชื่อมต่อ C3P0-> <bean id = "dataSource"> <property name = "driverclass" value = "{jdbc.dridclass}" <property name = "user" value = "$ {jdbc.username}" /> <property name = "รหัสผ่าน" value = "$ {jdbc.password}" /> </ebean> <! กำหนดค่า jdbctemplate โดยอัตโนมัติ)-> <bean id = "accountdao"> <property name = "dataSource" ref = "DataSource" /> </ebean> <!-! - - - - - - - - : การแยกพฤติกรรมการทำธุรกรรมการแยก: การแยกการทำธุรกรรมระดับการอ่านอย่างเดียว: อ่านอย่างเดียวย้อนกลับ-สำหรับ: ข้อยกเว้นใดที่เกิดขึ้นไม่ได้กลับมา:: ข้อยกเว้นใดที่เกิดขึ้นไม่ได้ย้อนกลับไปหมด: ข้อมูลการกำหนดค่า>-การกำหนดค่า-การกำหนดค่า-การกำหนดค่า-การกำหนดค่า-การกำหนดค่า- <aop: pointcut expression = "การดำเนินการ (* com.zs.spring.demo3.AccountService+.* (.. ))" id = "pointcut1"/> <!ทดสอบ:
/ *** @description: วิธีการจัดการธุรกรรมการประกาศของฤดูใบไม้ผลิสอง: การกำหนดค่า XML ที่ใช้ AspectJ*/ @runwith (springjunit4classrunner.class) @contextconfiguration ("classpath: applicationcontext3.xml") "AccountService") บริการบัญชีส่วนตัวบริการบัญชี; @Test โมฆะสาธารณะ demo1 () {accountService.transfer ("AAA", "BBB", 200d); --อิงตามคำอธิบายประกอบ
/ *** @Transactional การแพร่กระจาย: การแยกการทำธุรกรรมการแยกพฤติกรรม: การแยกการทำธุรกรรมระดับการแยกอย่างอ่านอย่างเดียว: อ่านอย่างเดียว* rollbackfor: ข้อยกเว้นที่เกิดขึ้น norollbackfor: ข้อยกเว้นที่เกิดขึ้นไม่ใช่การย้อนกลับ AccountServiceImpl ใช้งานบัญชี {// dao injecting transfer private accountdao accountdao; / *** @param out*: การโอนบัญชี* @param ใน*: โอนบัญชี* @param เงิน*: จำนวนเงินโอน*/ @Override โมฆะสาธารณะโอนเงิน (สตริงออก, สตริง, เงินสองครั้ง) {accountdao.outmoney (ออก, เงิน); // int i = 1/0; AccountDao.inmoney (เป็นเงิน); } โมฆะสาธารณะ setAccountdao (บัญชี daccountdao) {this.accountdao = accountdao; -ApplicationContext4.xml
<!-แนะนำไฟล์อสังหาริมทรัพย์ภายนอก-> <บริบท: สถานที่ตั้งสถานที่ตั้งสถานที่ = "classpath: jdbc.properties" /> <!-กำหนดค่าพูลการเชื่อมต่อ C3P0-> <bean id = "dataSource"> <property name = "driverclass" value = "{jdbc.dridclass}" <property name = "user" value = "$ {jdbc.username}" /> <property name = "รหัสผ่าน" value = "$ {jdbc.password}" /> </ebean> <! กำหนดค่า jdbctemplate โดยอัตโนมัติ)-> <bean id = "accountdao"> <property name = "dataSource" ref = "DataSource" /> </ebean> <!-! - - - - กำหนดค่า Transaction Manager-> <bean id = "transactionManager"> <property name = "dataSource" ref = "dataSource"/> </ebean> <!-เปิดธุรกรรมคำอธิบายประกอบ-> <tx: การทำธุรกรรมที่ขับเคลื่อนด้วยคำอธิบายประกอบทดสอบ:
@runwith (springjunit4classrunner.class) @contextconfiguration ("classpath: applicationcontext4.xml") การทำธุรกรรมระดับสาธารณะ transactiontest { / *** อย่าลืมฉีดคลาสพร็อกซี: เนื่องจากการให้บริการพร็อกซี @Test โมฆะสาธารณะ demo1 () {accountService.transfer ("AAA", "BBB", 200d); -สำหรับรหัสเฉพาะและฐานข้อมูลการอ้างอิงไฟล์โครงการรหัสที่สมบูรณ์:
http://xiazai.vevb.com/201805/yuanma/spring-transaction_jb51.rar
สรุป
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่าเนื้อหาของบทความนี้จะมีค่าอ้างอิงบางอย่างสำหรับการศึกษาหรือที่ทำงานของทุกคน หากคุณมีคำถามใด ๆ คุณสามารถฝากข้อความไว้เพื่อสื่อสาร ขอบคุณสำหรับการสนับสนุน Wulin.com