国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 數據庫 > MySQL > 正文

MySQL與Spring事務管理

2024-07-24 12:59:34
字體:
來源:轉載
供稿:網友

數據庫事務是保證在并發情況下能夠正確執行的重要支撐,MySQL常見的數據庫引擎中支持事務的是InnoDB,事務就是一系列操作,正確執行并提交,如果中途出現錯誤就回滾。事務要保證能夠正常的執行,就必須要保持ACID特性,這在前面的文章當中有提到,本文也偏重sPRing的事務管理配置demo因此不做過多的概念介紹,網上的資料已經比較豐富。

這是HeidiSQl截圖查看不同引擎的特性: 這里寫圖片描述

數據庫的事務的隔離性是有級別的,不同的級別具有不同的特性,應該在合適的條件下選擇合適的隔離級別,不同的數據庫產品支持的隔離級別可能不同,甲骨文支持三種,MySQL數據庫支持四種隔離級別,分別是:讀未提交,讀已提交,可重復讀,可串行。不同的隔離級別分別可以避免臟讀,不可重復讀,幻讀的情況。值得一提的是,避免不可重復讀和幻讀都是進行加鎖,不同的是一個是對行進行加鎖,避免幻讀是對表進行加鎖。還有就是鎖可以分為共享鎖和獨占鎖,一般來說為了避免事務的更新丟失,讀寫之間會進行加鎖,分為悲觀鎖與樂觀鎖,悲觀鎖就是普通的鎖,樂觀鎖就是不加鎖,在更新的時候再去驗證是否有被修改,如果被修改則讀取的數據為臟數據不能修改。這樣在修改比較多的情況下比較適合悲觀鎖,在讀取比較多的情況下就比較適合樂觀鎖。

spring作為開發平臺,對數據庫的訪問支持的很完善,對事務的支持也比較完善,主要分為兩種編程式事務與聲明式事務,編程式事務能夠更細的控制事務回滾與提交的粒度,但是需要在代碼中編寫,耦合性更高,并且與業務代碼混合在一起,這與spring的無入侵的特性相違背,因此一般會采用聲明式事務的方式進行事務管理,因為在很多需要操作數據的邏輯都需要進行事務管理,拋開不同開發者寫的代碼差異性不談,單從重復性的代碼導致系統難以維護,內聚性很差這點就足以證明這種方式不可取,但是這不正是AOP的使用場景嗎,因此使用切面編程技術生成動態代理完成事務管理,業務代碼更加的單純,。主要分為三大部分,數據源,事務管理器,代理機制。其中處于核心地位的接口為PlatformTransactionManager,它的定義比較簡單:// 獲取spring配置的事務傳播機制 TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;// 提交 void commit(TransactionStatus status) throws TransactionException;// 或則回滾 void rollback(TransactionStatus status) throws TransactionException;

getTransaction定義了事務的開啟范圍,這個可以在網上找到更詳細的講解,這里不累述。commit與rollback就是基本的事務控制機制。 AbstractPlatformTransactionManager實現了該接口,這個抽象類定義一些基本的對事務支持的操作,但是抽象了不同的orm框架對事務管理的細節。jdbc是通過dataSource Connection來進行事務管理,而hibernate是通過Sqlsession進行事務管理。使用jdbc進行事務管理,就注入DataSourceTransactionManager即可。并制定對應的數據源,然后只需要制定需要代理的類即可。 數據源的配置:

<bean id="driver" class="com.mysql.jdbc.Driver"></bean> <bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource"> <property name="username" value="${username}" /> <property name="passWord" value="${password}" /> <property name="url" value="${url}" /> <property name="driver" ref="driver" /> </bean>

首先我們制定事務管理器:

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean>

然后我們定義需要事務傳播機制,我們來創建一個常見,也可以采用其他的方式創建advice,這里的advice通知就是定義了需要做什么,這里就是 如果有事務加入事務,沒有的話創建新事務:

<tx:advice id="advice" transaction-manager="transactionManager"> <tx:attributes> <!-- 如果有事務加入事務,沒有的話創建新事務 --> <tx:method name="*" propagation="REQUIRED" timeout="3"/> </tx:attributes> </tx:advice>

做什么定義完了,就需要指定在哪里做(pointcut)即切點,代理的方式有很多種,可以使用默認的代理DefaultAdvisorAutoProxyCreator。也可以使用注解的方式,很靈活,主要就是明白定義好切點(一般spring支持較好的是方法級別的攔截)即可。這里我們使用比較方便的schema標簽支持aop代理:

<aop:config> <aop:pointcut id="txPointcut" expression="execution(* micro.test.spring.service..*Service*.*(..))" /> <aop:advisor advice-ref="advice" pointcut-ref="txPointcut"/> </aop:config>

很多時候我們引入新的xml標簽會報錯,這個時候檢查xml文件頭是否引入了相關的schema即可,這點是初學者很容易犯錯的地方。

<!-- 掃描到advice --> <context:component-scan base-package="micro.test.spring" /> <!-- mybatis中sqlSession由這個類來完成 --> <bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="mapperLocations"> <list> <value>classpath:/sqlmap/ComputerMapper.xml</value> </list> </property> </bean>

其他必要的配置跟本文不太相關就不貼了。 前面execution(* micro.test.spring.service..Service.*(..))就表示在這個包下面的所有方法都是切點,會被代理。這是service的一個方法,執行它:

public void testTransaction2() { Computer computer = new Computer(); computer.setBrand("test"); computerMapper.insert(computer);//事務會回滾 ComputerExample computerExample = new ComputerExample(); computerExample.or().andBrandEqualTo(computer.getBrand()); int a = 1; a /= 0; // 制造異常 computerMapper.insert(computer); }

如果沒事務管理機制,會插入一條記錄。引入了事務管理機制,拋出異常(spring要求運行時異常)就不會插入記錄,因為遇到了異常,當然如果去掉異常,兩條都會插入進去,值得一提的是我數據庫設置的默認應該不是讀未提交,因為在調試到還沒拋異常的時候也不會看到一條記錄,如果是讀未提交應該是看到出現了一條記錄然后又消失了(被回滾),測試了幾次,要么有0條,要么有兩條(正常執行)。沒有造成臟讀的情況至少應該是讀已提交。查詢了一下: 這里寫圖片描述 果然可重復讀,是能夠不免臟讀和不可重復度兩個問題的。但是無法避免幻讀。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 湖州市| 邵阳县| 沙湾县| 柳州市| 修武县| 遵化市| 通州市| 永靖县| 华宁县| 浏阳市| 大连市| 疏附县| 通城县| 甘孜县| 广安市| 黄山市| 平定县| 桃园县| 泸溪县| 绥化市| 土默特右旗| 章丘市| 夏河县| 通江县| 搜索| 莱西市| 云霄县| 渭源县| 乌拉特前旗| 垣曲县| 彰化县| 阜新| 建水县| 井研县| 郁南县| 高密市| 紫云| 五寨县| 莎车县| 玛沁县| 绥中县|