javascript
Spring事务隔离级别,事务传播行为
什么是事務:?
事務邏輯上的一組操作,組成這組操作的各個邏輯單元,要么一起成功,要么一起失敗.
Spring事務的隔離性(5種)
在講隔離界別前,我們先來講講下基礎知識
事務的特性(ACID)
原子性 (atomicity):強調事務的不可分割.
一致性 (consistency):事務的執(zhí)行的前后數據的完整性保持一致.
隔離性 (isolation):一個事務執(zhí)行的過程中,不應該受到其他事務的干擾
持久性(durability) :事務一旦結束,數據就持久到數據庫
?
可能發(fā)生的數據安全問題
臟讀:另一個事務還未提交,就已經讀到數據未提交的數據。
不可重復讀:在同一個事務中,讀取一次數據,當另一個數據修改數據提交事務后,再次讀取數據與上一次讀取數據不同。
幻讀:在同一個事務中,讀取一次數據的數量。當另一個事務增加/刪除一些數據時,數據數量與第一次不同。
?
MySQL默認隔離級別,可重復讀
1.讀未提交(最低事務隔離界別):可能發(fā)生問題?臟讀,不可重復讀,幻讀
2.讀已提交? 解決問題:臟讀??可能發(fā)生問題 不可重復讀,幻讀
3.可重復讀(默認隔離級別)?解決問題:臟讀 ,?不可重復讀? 可能發(fā)生問題幻讀
4.串行化?(最高事務隔離級別) 解決問題:臟讀,不可重復讀,幻讀? ?
?
不難想象隔離級別越高,發(fā)生的問題就越少。當然也就意味著同步數據消耗的資源更多。
相信MySQL能把可重復讀指定為默認隔離級別,說明其性能已經非常棒了
?
Spring隔離級別
1.ISOLATION_DEFAULT? ?使用數據庫默認隔離級別
2.ISOLATION_READ_UNCOMMITTED?讀未提交
3.ISOLATION_READ_COMMITTED 讀已提交
4.ISOLATION_REPEATABLE_READ 可重復讀
5.ISOLATION_SERIALIZABLE 串行化
?
Spring事務的傳播行為(7種)
事務傳播:當一個方法中調用另外一個方法時,處理這兩個方法間的事務行為(是基于Spring的AOP實現(xiàn)的)
舉例:
1 @Transactional(isolation = Isolation.SERIALIZABLE) 2 public void method1() { 3 method2(); 4 } 5 6 @Transactional(isolation = Isolation.READ_COMMITTED) 7 public void method2() { 8 }現(xiàn)在兩個方法事務的隔離級別顯然不同,那我們對于這種情況就要使用Spring事務傳播行為來解決。
?
propagation(傳播)
在當前事務中運行:
PROPAGATION_SUPPORTS(method1事務存在,使用method1事務。method1事務不存在,以非事務方式執(zhí)行)
不再當前事務中運行:
?
事務的實現(xiàn)?
接下來我們看看都可以怎么實現(xiàn)Spring的事務
1.編程式事務管理
手動編寫事務代碼(很少使用)
2.聲明式事務管理
基于TransactionProxyFactoryBean方式(很少使用)
基于Aspect的XML方式(常用)
基于注解方式(常用)
?
?
實驗代碼
dao層方法
1 @Repository("MyDao") 2 public interface MyDao { 3 int inCount(@Param("name") String name, @Param("count") double count);//增加錢 4 5 int outCount(@Param("name") String name, @Param("count") double count);//減少錢 6 7 double getCount(@Param("name") String name);//查詢錢 8 }查詢余額
1 public interface GetCountService { 2 double getCount(String name); 3 } 1 //獲取當前余額 2 @Service 3 public class GetCountServiceImpl implements GetCountService { 4 5 @Autowired 6 private MyDao myDao; 7 8 public double getCount(String name) { 9 return myDao.getCount(name); 10 } 11 }轉出錢
1 public interface OutService { 2 boolean out(String out, double count); 3 } 1 @Service 2 public class OutServiceImpl implements OutService { 3 @Autowired 4 private MyDao myDao; 5 6 public boolean out(String out, double count) { 7 return myDao.outCount(out,count)>0; 8 } 9 }轉入錢
1 public interface InService { 2 boolean in(String in, double count); 3 } 1 @Service 2 public class InServiceImpl implements InService { 3 @Autowired 4 private MyDao myDao; 5 6 public boolean in(String in, double count) { 7 return myDao.inCount(in, count) > 0; 8 } 9 }轉賬
1 public interface MyService { 2 boolean transferCount(String out, String in, double count); 3 } 1 //實現(xiàn)轉賬 2 @Service 3 @Transactional 4 //(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT) 5 public class MyServiceImpl implements MyService { 6 7 @Resource 8 private GetCountService getCountService; 9 10 @Resource 11 private OutService outService; 12 13 @Resource 14 private InService inService; 15 16 17 // 解耦是為了更多的復用 18 // 對于代碼模塊的修改,不影響接口的使用 19 public boolean transferCount(String out, String in, double count) { 20 //判斷傳出金額與當前金額 21 if (getCountService.getCount(out) < count) return false; 22 //轉出錢 23 if (!outService.out(out, count)) return false; 24 25 //制造異常 26 //int i = 10 / 0; 27 28 //轉入錢 29 return inService.in(in, count); 30 } 31 }當關上注釋的時候,能實現(xiàn)正常的轉賬功能。
但是手動制造異常除數等于0后發(fā)現(xiàn),傳出人的錢少了,但是轉入人的錢缺沒有發(fā)生變化,沒有保證數據的原子性。
?
基于Aspect的XML方式
1 <!-- 配置事務的通知(事務增強) --> 2 <tx:advice id="txAdvice" transaction-manager="transactionManager"> 3 <tx:attributes> 4 <!--以transfer開頭的方法 --> 5 <tx:method name="transfer*" isolation="DEFAULT" propagation="REQUIRED"/> 6 </tx:attributes> 7 </tx:advice> 8 <!-- 配置切面 --> 9 <aop:config> 10 <!-- 配置切入點 --> 11 <!--*任意返回值 *任意方法 (..)任意參數 --> 12 <aop:pointcut id="pointcut1" expression="execution(* com.hg.service.*+.*(..))"/> 13 <!-- 配置切面 --> 14 <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut1"/> 15 </aop:config>?
基于注解方式(常用)
首先在XML中配置事務管理器
1 <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 2 <!--注入數據庫連接池--> 3 <property name="dataSource" ref="dataSource"/> 4 </bean> 5 6 <!--開啟注解--> 7 <tx:annotation-driven transaction-manager="transactionManager"/>開啟注解
@Transactional //這些都是spring事務的默認屬性,timeout是直接指定的時間 @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT,readOnly = false,timeout = 1000,rollbackFor = Exception.class)//這兩種實現(xiàn)效果相同
?
對比
第一種明顯是一種AOP編程思想(面向切面)
當對所有的切面指定好規(guī)則后,所有的方法都不需要在進行配置。
優(yōu)點:
代碼量較少
通過制定規(guī)則(insert開頭的方法,delete開頭的方法,select開頭的方法,update開頭的方法),不易出錯
?
第二種注解的方式
優(yōu)點
較第一種方法更為靈活。但是在某些情況下冗余太多,導致修改維護的困難
?
結論,沒有最好的技術,只有最符合業(yè)務的技術,小伙根據自己的情況選擇合適的方式實現(xiàn)spring的事務吧。
?
轉載于:https://www.cnblogs.com/Gang-Bryant/p/10887216.html
總結
以上是生活随笔為你收集整理的Spring事务隔离级别,事务传播行为的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 杨字网名130个
- 下一篇: gradle idea java ssm