1. 程式人生 > >Spring系列之事務的控制 註解實現+xml實現+事務的隔離等級

Spring系列之事務的控制 註解實現+xml實現+事務的隔離等級

## Spring系列之事務的控制 註解實現+xml實現 在前面我寫過一篇關於事務的文章,大家可以先去看看那一篇再看這一篇,學習起來會更加得心應手 **連結**:[https://blog.csdn.net/pjh88/article/details/107574137](https://blog.csdn.net/pjh88/article/details/107574137) ## 程式設計式事務控制物件 **事務管理器:PlatformTransactionManager** PlatformTransactionManager是事務的管理器,他提供了我們常用的事務操作方法 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200926211340752.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3BqaDg4,size_16,color_FFFFFF,t_70#pic_center)為什麼PlatformTransactionManager是介面型別? 因為不同的dao層技術有不同的實現類 Dao層是jdbc時:org.springframework.jdbc.datasource.DataSourceTransactionManager Dao層是mybatis時:org.springframework.orm.hibernate5.HibernateTransactionManager **事務的定義資訊物件:TransactionDefinition** TransactionDefinition **裡面的方法** ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200926212200569.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3BqaDg4,size_16,color_FFFFFF,t_70#pic_center) ** ## 事務的隔離級別 ** **ISOLATION_READ_UNCOMMITTED(讀未提交)** **實質**:一個事務讀取另一個事務未提交的資料 **例子**:老闆要給程式設計師發工資,程式設計師的工資是3.6萬/月。但是發工資時老闆不小心按錯了數字,按成3.9萬/月,該錢已經打到程式設計師的戶口,但是事務還沒有提交,就在這時,程式設計師去檢視自己這個月的工資,發現比往常多了3千元,以為漲工資了非常高興。但是老闆及時發現了不對,馬上回滾差點就提交了的事務,將數字改成3.6萬再提交。 **分析**:實際程式設計師這個月的工資還是3.6萬,但是程式設計師看到的是3.9萬。他看到的是老闆還沒提交事務時的資料。這就是髒讀。 **ISOLATION_READ_COMMITTED(讀已提交)** **實質**:一個使用者讀取另一個使用者已提交的資料 **事例**:程式設計師拿著信用卡去享受生活(卡里當然是只有3.6萬),當他埋單時(程式設計師事務開啟),收費系統事先檢測到他的卡里有3.6萬,就在這個時候!!程式設計師的妻子要把錢全部轉出充當家用,並提交。當收費系統準備扣款時,再檢測卡里的金額,發現已經沒錢了(第二次檢測金額當然要等待妻子轉出金額事務提交完)。程式設計師就會很鬱悶,明明卡里是有錢的… **分析**:這就是讀提交,若有事務對資料進行更新(UPDATE)操作時,讀操作事務要等待這個更新操作事務提交後才能讀取資料,可以解決髒讀問題。但在這個事例中,出現了一個事務範圍內兩個相同的查詢卻返回了不同資料,這就是不可重複讀。 **ISOLATION_REPEATABLE_READ(重複讀)** **實質**:一個事務在讀取資料時,其他事務不允許進行修改操作 **事例**:程式設計師拿著信用卡去享受生活(卡里當然是只有3.6萬),當他埋單時(事務開啟,不允許其他事務的UPDATE修改操作),收費系統事先檢測到他的卡里有3.6萬。這個時候他的妻子不能轉出金額了。接下來收費系統就可以扣款了。 **分析**:重複讀可以解決不可重複讀問題。寫到這裡,應該明白的一點就是,不可重複讀對應的是修改,即UPDATE操作。但是可能還會有幻讀問題。因為幻讀問題對應的是插入INSERT操作,而不是UPDATE操作。 **ISOLATION_SERIALIZABLE(幻讀)** **事例**:程式設計師某一天去消費,花了2千元,然後他的妻子去檢視他今天的消費記錄(全表掃描FTS,妻子事務開啟),看到確實是花了2千元,就在這個時候,程式設計師花了1萬買了一部電腦,即新增INSERT了一條消費記錄,並提交。當妻子列印程式設計師的消費記錄清單時(妻子事務提交),發現花了1.2萬元,似乎出現了幻覺,這就是幻讀。 ** ## 事務的傳播行為 ** **REQUIRED**:如果當前沒有事務,就新建一個事務,如果已經存在一個事務中,加入到這個事務中。一般的選擇(預設值) **SUPPORTS**:支援當前事務,如果當前沒有事務,就以非事務方式執行(沒有事務) **MANDATORY**:使用當前的事務,如果當前沒有事務,就丟擲異常 **REQUERS_NEW**:新建事務,如果當前在事務中,把當前事務掛起。 **NOT_SUPPORTED**:以非事務方式執行操作,如果當前存在事務,就把當前事務掛起 **NEVER**:以非事務方式執行,如果當前存在事務,丟擲異常 **NESTED**:如果當前存在事務,則在巢狀事務內執行。如果當前沒有事務,則執行 REQUIRED 類似的操作 **超時時間**:預設值是-1,沒有超時限制。如果有,以秒為單位進行設定 **是否只讀**:建議查詢時設定為只讀 ## TransactionStatus:事務的具體執行狀態 **TransactionStatus介面提供的是事務具體的執行狀態,方法如下** ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200926214001592.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3BqaDg4,size_16,color_FFFFFF,t_70#pic_center) **程式設計式事務控制的三大物件** PlatformTransactionManager TransactionDefinition TransactionStatus ## 基於XML的宣告式事務控制 Spring的宣告式事務控制顧名思義就是使用宣告的方式來處理事務,這裡的宣告指的是在配置檔案中宣告,Spring配置檔案中的宣告式處理來代替程式碼式的事務處理 **宣告式事務處理的作用** 事務處理是不侵入開發的元件,具體來說,業務邏輯物件不會意識帶正在處於事務處理之中,事實上也應該如此,因為事務管理是出於系統層面的職務,而不是業務邏輯處理的一部分,如果要改變事務管理策劃的話,也只需要在定義檔案中重新配置即可 在不需要事務管理的時候,只要在設定的檔案上修改一下,即可移除事務管理服務,不需要改變程式碼重新編譯,這樣維護起來更加方便 Spring事務控制的底層就是AOP ## 宣告式事務控制的實現 **切點**:需要被事務管理的方法,即業務方法 **通知/增強**:事務增強 **切面**:二者結合 ## 下面通過一個銀行業務轉賬的案例來方便大家理解 **1.建立資料庫和實體** **表名**:account **欄位名**:moey--錢,Name--客戶名 ```java CREATE TABLE account( NAME VARCHAR(10), money DOUBLE ); ``` **插入三個欄位值** ```java INSERT INTO account VALUE('tom',1),('bob',2),('jack',3); ``` ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20201002191543689.png#pic_center) **2.需要匯入的座標** ```java 4.0.0 org.example spring-mysql 1.0-SNAPSHOT mysql mysql-connector-java 5.1.32 com.alibaba druid 1.1.10 c3p0 c3p0 0.9.1.2 org.springframework spring-context 5.0.5.RELEASE
org.springframework spring-tx 5.0.3.RELEASE org.springframework spring-jdbc 5.0.3.RELEASE org.springframework spring-test 5.0.5.RELEASE junit junit 4.13 org.aspectj
aspectjweaver 1.8.13
org.junit.jupiter junit-jupiter RELEASE compile
``` **3.建立實體類** ```java package com.pjh.account; public class account { private double money; private String name; @Override public String toString() { return "account{" + "money=" + money + ", name='" + name + '\'' + '}'; } public double getMoney() { return money; } public void setMoney(double money) { this.money = money; } public String getName() { return name; } public void setName(String name) { this.name = name; } } ``` **4.dao層(執行語句,與資料庫互動)** **介面** ```java package com.pjh.dao; public interface ServiceDao { public void inman(String inName,double money); public void outman(String outName,double money); } ``` **實現類** ```java package com.pjh.dao.imp; import com.pjh.dao.ServiceDao; import org.springframework.jdbc.core.JdbcTemplate; public class ServiceDaoImp implements ServiceDao { private JdbcTemplate jdbcTemplate; public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } public void inman(String inName, double money) { jdbcTemplate.update("update account set money=money-? where name =?",money,inName); } public void outman(String outName, double money) { jdbcTemplate.update("update account set money=money+? where name =?",money,outName); } } ``` **5.service層** **介面** ```java package com.pjh.service; public interface service { public void trasfer(String inName,String outName,double money); } ``` **實現類** ```java package com.pjh.service.Imp; import com.pjh.dao.imp.ServiceDaoImp; import com.pjh.service.service; import org.springframework.beans.factory.annotation.Autowired; public class serviceImp implements service { private ServiceDaoImp serviceDaoImp; public void setServiceDaoImp(ServiceDaoImp serviceDaoImp) { this.serviceDaoImp = serviceDaoImp; } public void trasfer(String inName, String outName, double money) { serviceDaoImp.inman(inName,money); serviceDaoImp.outman(outName,money); } } ``` **6.applicationContext配置檔案** ```java
``` **7.主函式** ```java package com.pjh.control; import com.pjh.service.Imp.serviceImp; import com.pjh.service.service; import org.springframework.context.support.ClassPathXmlApplicationContext; public class control2 { public static void main(String[] args) { ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); service bean1 =(service) classPathXmlApplicationContext.getBean(service.class); bean1.trasfer("tom","jack",100); } } ``` **結果** 成功轉賬 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20201002224503259.png#pic_center) ** ## 下面我們重點來講講切點方法的事務配置 ** ```java ``` :**代表事務引數方法的配置** **這個部分一定要重點掌握這是核心** ```java name:切點方法名稱 isolation:事務的隔離級別 propogation:事務的傳播行為 timeout:超時時間 read-only:是否只讀 ``` ## 使用註解的方式進行事務的配置 **1.dao層** ```java package com.pjh.dao.imp; import com.pjh.dao.ServiceDao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; @Repository("ServiceDaoImp") public class ServiceDaoImp implements ServiceDao { @Autowired private JdbcTemplate jdbcTemplate; public void inman(String inName, double money) { jdbcTemplate.update("update account set money=money-? where name =?",money,inName); } public void outman(String outName, double money) { jdbcTemplate.update("update account set money=money+? where name =?",money,outName); } } ``` **2.service層** ```java package com.pjh.service.Imp; import com.pjh.dao.imp.ServiceDaoImp; import com.pjh.service.service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service("serviceImp") @Transactional public class serviceImp implements service { @Autowired private ServiceDaoImp serviceDaoImp; public void trasfer(String inName, String outName, double money) { serviceDaoImp.inman(inName,money); //int a=1/0; serviceDaoImp.outman(outName,money); } } ``` **3.編寫applicationContext的內容** ```java ``` **小總結** 1.使用 @Transactional 在需要進行事務控制的類或是方法上修飾,註解可用的屬性同 xml 配置方式,例如隔離級別、傳播行為等。 註解使用在類上,那麼該類下的所有方法都使用同一套註解引數配置。 使用在方法上,不同的方法可以採用不同的事務引數配置。 2.Xml配置檔案中要開啟事務的註解驅動 ## 以上就是Spring系列之事務的控制 註解實現+xml實現的知識點,如果各位覺得有幫助還請點贊關注支援作者,我也會在學習過程中不斷更新文章,目前主要是java開發和資料結構的一些知識,願我們一同進步,圓夢大廠,歡迎私信評論交流 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20201002230451641.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3BqaDg4,size_16,color_FFFFFF,t_70#pic_