日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Spring JDBC-事务方法嵌套调用解读

發布時間:2025/3/21 javascript 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring JDBC-事务方法嵌套调用解读 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

  • Spring事務傳播機制回顧
  • 相互嵌套的服務方法
  • 源碼

Spring事務傳播機制回顧

關于Spring事務的一個錯誤的說法:一個事務方法中不應該調用另外一個事務方法,否則將產生兩個事務,其實這是不正確的。

這是因為未正確認識Spring事務傳播機制而造成的誤解。 Spring對事務控制的支持統一在TransactionDefinition類中描述

我們來看下該類中的接口方法

  • int getPropagationBehavior() 事務的傳播行為
  • int getIsolationLevel(); 事務的隔離級別
  • int getTimeout();事務的過期時間
  • boolean isReadOnly();事務的讀、寫特性
  • String getName();事務的名稱

除了事務的傳播行為外,事務的其他特性Spring是借助底層資源的功能來完成的,Spring無非只充當個代理的角色。但是事務的傳播行為卻是Spring憑借自身的框架提供的功能

所謂事務傳播的行為,就是多個事務方法相互調用時,事務如何在這些方法間傳播。 Spring在TransactionDefinition接口中規定了7種類型的事務傳播行為,它們規定了事務方法和事務方法發生嵌套調用時事務如何進行傳播:

事務傳播行為類型說明
PROPAGATION_REQUIRED如果當前沒有事務,就新建一個事務,如果已經存在一個事務中,加入到這個事務中。這是最常見的選擇
PROPAGATION_SUPPORTS支持當前事務,如果當前沒有事務,就以非事務方式執行。
PROPAGATION_MANDATORY使用當前的事務,如果當前沒有事務,就拋出異常。
PROPAGATION_REQUIRES_NEW新建事務,如果當前存在事務,把當前事務掛起
PROPAGATION_NOT_SUPPORTED以非事務方式執行操作,如果當前存在事務,就把當前事務掛起
PROPAGATION_NEVER以非事務方式執行,如果當前存在事務,則拋出異常。
PROPAGATION_NESTED如果當前存在事務,則在嵌套事務內執行。如果當前沒有事務,則執行與PROPAGATION_REQUIRED類似的操作。

當使用PROPAGATION_NESTED時,底層的數據源必須基于JDBC 3.0,并且實現者需要支持保存點事務機制。

Spring默認的事務傳播行為是PROPAGATION_REQUESTED, 它適合絕大多數情況。

如果多個ServiceX#methodX() 均工作下在事務環境下(均被Spring事務增強),且程序中存在調用鏈Service1#method1()—->Service2#method2()——>Service#method3(),那么這3個服務類的3個方法通過Spring的事務傳播機制都工作在同一個事務中。


相互嵌套的服務方法

我們來舉個例子,TeacherService#doSomething()方法內部調用了 調用本類的udpateTeacherInfo還有StudentService#updateSutdent()方法,這兩個類都繼承于BaseService,類結構如下:

package com.xgj.dao.transaction.nestedCall.service;import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service;import com.xgj.dao.transaction.nestedCall.dao.TeacherDao; import com.xgj.dao.transaction.nestedCall.domain.Student; import com.xgj.dao.transaction.nestedCall.domain.Teacher;/*** * * @ClassName: TeacherService* * @Description: @Service標注的service層 繼承BaseService* * @author: Mr.Yang* * @date: 2017年9月24日 下午4:56:35*/@Service public class TeacherService extends BaseService {Logger logger = Logger.getLogger(TeacherService.class);private TeacherDao teacherDao;private StudentService studentService;@Autowiredpublic void setTeacherDao(TeacherDao teacherDao) {this.teacherDao = teacherDao;}@Autowiredpublic void setStudentService(StudentService studentService) {this.studentService = studentService;}/*** * * @Title: init* * @Description: 改方法嵌套調用了本類的其他方法以及其他類的方法* * * @return: void*/public void doSomething() {logger.info("before TeacherService#udpateTeacherInfo");// 調用本類的其他方法udpateTeacherInfo(simulateTeacher());logger.info("after TeacherService#udpateTeacherInfo");// 調用其他類的方法logger.info("before StudentService#updateSutdent");studentService.updateSutdent(simulateStudent());logger.info("after StudentService#updateSutdent");}public void udpateTeacherInfo(Teacher teacher) {teacherDao.updateTeacher(teacher);}/*** * * @Title: simulateTeacher* * @Description: 模擬獲取一個teacher實例* * @return* * @return: Teacher*/private Teacher simulateTeacher() {Teacher teacher = new Teacher();teacher.setName("FTT");teacher.setAge(88);teacher.setSex("FF");teacher.setTeacherId(2);return teacher;}private Student simulateStudent() {Student student = new Student();student.setName("FSS");student.setAge(22);student.setSex("MM");student.setStudentId(2);return student;}}

配置文件:

<?xml version="1.0" encoding="UTF-8" ?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsd"><!-- 掃描類包,將標注Spring注解的類自動轉化Bean,同時完成Bean的注入 --><context:component-scan base-package="com.xgj.dao.transaction.nestedCall" /><!-- 使用context命名空間,配置數據庫的properties文件 --><context:property-placeholder location="classpath:spring/jdbc.properties" /><bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"destroy-method="close" p:driverClassName="${jdbc.driverClassName}"p:url="${jdbc.url}" p:username="${jdbc.username}" p:password="${jdbc.password}" /><!-- 配置Jdbc模板 --><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"p:dataSource-ref="dataSource" /><!--事務管理器,通過屬性引用數據源 --><bean id="jdbcManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"p:dataSource-ref="dataSource"/><!-- 通過以下配置為繼承BaseService的所有子類的所有public方法添加事務增強 --><aop:config proxy-target-class="true"><!-- 切點 --><aop:pointcut id="serviceJdbcMethod" expression="within(com.xgj.dao.transaction.nestedCall.service.BaseService+)"/><!-- 切面 --><aop:advisor pointcut-ref="serviceJdbcMethod" advice-ref="txAdvice"/></aop:config><!-- 增強,供aop:advisor引用 --><tx:advice id="txAdvice" transaction-manager="jdbcManager"><tx:attributes><tx:method name="*"/></tx:attributes></tx:advice></beans>

通過Spring配置為TeacherService以及StudentService中的所有公共方法都添加Spring AOP的事務增強,讓TeacherService的doSomething()和udpateTeacherInfo()以及StudentService的updateSutdent方法都工作在事務環境下。

關鍵代碼:

<aop:pointcut id="serviceJdbcMethod" expression="within(com.xgj.dao.transaction.nestedCall.service.BaseService+)"/>

我們將日志級別調整為DEBUG,運行測試類

package com.xgj.dao.transaction.nestedCall.service;import org.junit.After; import org.junit.Before; import org.junit.Test; import org.springframework.context.support.ClassPathXmlApplicationContext;public class TeacherServiceTest {ClassPathXmlApplicationContext ctx = null;TeacherService teacherService = null;@Beforepublic void initContext() {// 啟動Spring 容器ctx = new ClassPathXmlApplicationContext("classpath:com/xgj/dao/transaction/nestedCall/conf_tx_nestedCall.xml");teacherService = ctx.getBean("teacherService", TeacherService.class);System.out.println("initContext successfully");}@Testpublic void testNestedCallInOneTransaction() {teacherService.doSomething();}@Afterpublic void closeContext() {if (ctx != null) {ctx.close();}System.out.println("close context successfully");} }

觀察日志:

2017-09-24 18:36:23,428 DEBUG [main] (AbstractPlatformTransactionManager.java:367) - Creating new transaction with name [com.xgj.dao.transaction.nestedCall.service.TeacherService.doSomething]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT 2017-09-24 18:36:23,777 DEBUG [main] (DataSourceTransactionManager.java:248) - Acquired Connection [jdbc:oracle:thin:@172.25.246.11:1521:testbed, UserName=CC, Oracle JDBC driver] for JDBC transaction 2017-09-24 18:36:23,781 DEBUG [main] (DataSourceTransactionManager.java:265) - Switching JDBC Connection [jdbc:oracle:thin:@172.25.246.11:1521:testbed, UserName=CC, Oracle JDBC driver] to manual commit 2017-09-24 18:36:23,820 INFO [main] (TeacherService.java:52) - before TeacherService#udpateTeacherInfo 2017-09-24 18:36:23,824 DEBUG [main] (JdbcTemplate.java:869) - Executing prepared SQL update 2017-09-24 18:36:23,825 DEBUG [main] (JdbcTemplate.java:616) - Executing prepared SQL statement [update teacher set name = ? ,age = ? ,sex = ? where id = ?] 2017-09-24 18:36:23,974 DEBUG [main] (JdbcTemplate.java:879) - SQL update affected 1 rows 2017-09-24 18:36:23,978 INFO [main] (TeacherDaoImpl.java:64) - updateTeacher successfully 2017-09-24 18:36:23,978 INFO [main] (TeacherService.java:55) - after TeacherService#udpateTeacherInfo 2017-09-24 18:36:23,978 INFO [main] (TeacherService.java:58) - before StudentService#updateSutdent 2017-09-24 18:36:23,978 DEBUG [main] (AbstractPlatformTransactionManager.java:476) - Participating in existing transaction 2017-09-24 18:36:24,004 DEBUG [main] (JdbcTemplate.java:869) - Executing prepared SQL update 2017-09-24 18:36:24,005 DEBUG [main] (JdbcTemplate.java:616) - Executing prepared SQL statement [update student set name = ? ,age = ? ,sex = ? where id = ?] 2017-09-24 18:36:24,007 DEBUG [main] (JdbcTemplate.java:879) - SQL update affected 1 rows 2017-09-24 18:36:24,007 INFO [main] (StudentDaoImpl.java:82) - updateStudent successfully 2017-09-24 18:36:24,008 INFO [main] (TeacherService.java:60) - after StudentService#updateSutdent 2017-09-24 18:36:24,008 DEBUG [main] (AbstractPlatformTransactionManager.java:759) - Initiating transaction commit 2017-09-24 18:36:24,008 DEBUG [main] (DataSourceTransactionManager.java:310) - Committing JDBC transaction on Connection [jdbc:oracle:thin:@172.25.246.11:1521:testbed, UserName=CC, Oracle JDBC driver]

Creating new transaction with name [com.xgj.dao.transaction.nestedCall.service.TeacherService.doSomething]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT

為TeacherService#doSomething開啟一個事務, 然后直接執行udpateTeacherInfo方法,由于doSomething和udpateTeacherInfo在一個類中,沒有觀察到有事務傳播行為的發生,

然而當執行到updateSutdent方法時,我們觀察到一個事務傳播行為: Participating in existing transaction ,這說明 StudentService#updateSutdent方法添加到了TeacherService#doSomething()方法的事務上下文中,二者共享同一個事務。 所以最終的結果是TeacherService的doSomething 和 udpateTeacherInfo 以及 StudentService#updateSutdent()方法工作在同一個事務中。

最后 Initiating transaction commit—-提交事務


源碼

代碼已托管到Github—> https://github.com/yangshangwei/SpringMaster

總結

以上是生活随笔為你收集整理的Spring JDBC-事务方法嵌套调用解读的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 爱爱视频在线免费观看 | 久久视频一区二区三区 | 久久久久人妻精品色欧美 | 日本福利一区二区 | 精品久久香蕉国产线看观看亚洲 | 国产精品午夜在线 | 成年人精品视频 | 俄罗斯精品一区二区三区 | a√天堂网| 亚洲美女视频网站 | 久久久久久久97 | 国产视频一区二区三区在线观看 | 80日本xxxxxxxxx96 亚洲国产精品视频在线 | 国产精品制服丝袜 | 天天草天天操 | 午夜青青草 | 欧美影院久久 | 波多野结衣一区二区三区中文字幕 | 性欧美8khd高清极品 | 白浆导航| 中文字幕在线日亚洲9 | 影音先锋亚洲精品 | 日韩av无码中文字幕 | 美女色av| 中文字幕一区二区在线观看 | 女人久久 | 小嫩女直喷白浆 | 国产成人免费视频网站 | 日韩一级高清 | 91精品国产综合久久福利 | av免费看网站 | 在线日韩国产 | 欧美日韩中文字幕一区二区三区 | 体内射精一区二区 | 免费三片在线观看网站v888 | 美国三级视频 | 麻豆911| 在线成人免费电影 | 香港三级在线视频 | av电影中文字幕 | 午夜精品毛片 | 中文不卡av | 天天干天天操 | 中文字幕 亚洲一区 | 国产精品成人免费 | 一区二视频| 国产一区二区三区四区在线观看 | 国产香蕉视频在线观看 | 天堂在线一区二区 | 成人日批 | 日本欧美激情 | 亚洲小视频在线播放 | 秋霞一区| 中文字字幕在线中文乱码 | 青春草在线视频免费观看 | 青草青青视频 | jizzjizz美国| 人人草人人澡 | 蓝牛av | 亚洲人xxxx| 午夜精品三级久久久有码 | 在线免费观看日韩 | www.国产com | 午夜精品久久久久久99热 | 美女扒开尿口给男人捅 | 国产成人免费电影 | 成人777| 亚洲精品国产成人无码 | 欧美精品成人在线 | 欧洲精品在线观看 | 国产chinese| 欧美做爰性生交视频 | 四虎网站 | 91春色| 91av免费观看 | 欧美人妻一区二区 | 国产国语性生话播放 | 亚洲成人中文字幕在线 | 久久免费黄色网址 | 久久精品视频99 | 性色av蜜臀av | 中文字幕一区二区三区视频 | 丰满少妇被猛烈进入无码 | 日韩国产第一页 | 最近免费中文字幕 | 四月婷婷 | 免费日皮视频 | 国产xxx在线观看 | 24小时日本在线www免费的 | 九九视频在线 | www.久久久久久久 | 热热色原网址 | 西西人体高清44rt·net | 无码人妻少妇色欲av一区二区 | 有码在线视频 | 超碰午夜 | 丰满少妇熟乱xxxxx视频 | 美女喷液视频 | 日韩午夜视频在线观看 |