SpringBoot事務詳細簡介

重要概念

自動提交模式

對于mysql數據庫,默認情況下,數據庫處于自動提交模式。每一條語句處于一個單獨的事務中,在這條語句執行完畢時,如果執行成功則隱式的提交事務,如果執行失敗則隱式的回滾事務。對于正常的事務管理,是一組相關的操作處于一個事務之中,因此必須關閉數據庫的自動提交模式,下面是查看方式:

查看是否自動提交命令(ON表示開啟自動提交,值為1,OFF表示關閉自動提交,值為0):

show?variables?like?'autocommit';

關閉自動提交后,則用戶將一直處于某個事務中,直到執行一條commit提交或rollback語句才會結束當前事務重新開始一個新的事務。

DataSource?connection?=?masterDataSource.getConnection(); connection.setAutoCommit(false);

事務隔離級別

隔離級別是指若干個并發的事務之間的隔離程度。TransactionDefinition 接口中定義了五個表示隔離級別的常量:

1、TransactionDefinition.ISOLATION_DEFAULT:這是默認值,表示使用底層數據庫的默認隔離級別。對大部分數據庫而言,通常這值就是TransactionDefinition.ISOLATION_READ_COMMITTED。?

2、TransactionDefinition.ISOLATION_READ_UNCOMMITTED:該隔離級別表示一個事務可以讀取另一個事務修改但還沒有提交的數據。該級別不能防止臟讀,不可重復讀和幻讀,因此很少使用該隔離級別。比如postgresql實際上并沒有此級別。?

3、TransactionDefinition.ISOLATION_READ_COMMITTED:該隔離級別表示一個事務只能讀取另一個事務已經提交的數據。該級別可以防止臟讀,這也是大多數情況下的推薦值。?

4、TransactionDefinition.ISOLATION_REPEATABLE_READ:該隔離級別表示一個事務在整個過程中可以多次重復執行某個查詢,并且每次返回的記錄都相同。該級別可以防止臟讀和不可重復讀。?

5、TransactionDefinition.ISOLATION_SERIALIZABLE:所有的事務依次逐個執行,這樣事務之間就完全不可能產生干擾,也就是說,該級別可以防止臟讀、不可重復讀以及幻讀。但是這將嚴重影響程序的性能。通常情況下也不會用到該級別。

事務傳播行為?

所謂事務的傳播行為是指,如果在開始當前事務之前,一個事務上下文已經存在,此時有若干選項可以指定一個事務性方法的執行行為。在TransactionDefinition定義中包括了如下幾個表示傳播行為的常量:

1、TransactionDefinition.PROPAGATION_REQUIRED:如果當前存在事務,則加入該事務;如果當前沒有事務,則創建一個新的事務。這是默認值。?

2、TransactionDefinition.PROPAGATION_REQUIRES_NEW:創建一個新的事務,如果當前存在事務,則把當前事務掛起。?

3、TransactionDefinition.PROPAGATION_SUPPORTS:如果當前存在事務,則加入該事務;如果當前沒有事務,則以非事務的方式繼續運行。?

4、TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事務方式運行,如果當前存在事務,則把當前事務掛起。?

5、TransactionDefinition.PROPAGATION_NEVER:以非事務方式運行,如果當前存在事務,則拋出異常。?

6、TransactionDefinition.PROPAGATION_MANDATORY:如果當前存在事務,則加入該事務;如果當前沒有事務,則拋出異常。?

7、TransactionDefinition.PROPAGATION_NESTED:如果當前存在事務,則創建一個事務作為當前事務的嵌套事務來運行;如果當前沒有事務,則該取值等價于TransactionDefinition.PROPAGATION_REQUIRED。

保護點(Savepoints)

首先要知道savepoint就是為回退做的,savepoint的個數沒有限制,savepoint和虛擬機中快照類似. savepoint是事務中的一點。用于取消部分事務,當結束事務時,會自動的刪除該事務中所定義的所有保存點。

當執行rollback時,通過指定保存點可以回退到指定的點。?

回退事務的幾個重要操作?

1、設置保存點 savepoint a?

2、取消保存點a之后事務 rollback to a?

3、取消全部事務 rollback?

注意:這個回退事務,必須是沒有commit前使用的;

public?class?UserRepository?{ ? 	 	private?DataSource?masterDataSource; 	private?Connection?connection?=?null; 	@Autowired 	public?void?setMasterDataSource(DataSource?masterDataSource)?{ 		this.masterDataSource?=?masterDataSource; 	} ? ? 	@Transactional 	public?boolean?save(User?user)?{ 		try?{ 			connection?=?masterDataSource.getConnection(); 			connection.setAutoCommit(false); 			//設置保護點 			Savepoint?saveUser?=?connection.setSavepoint("saveUser"); 			PreparedStatement?prepareStatement?=?connection.prepareStatement("insert?into?user(id,name,age)?values(?,?,?)"); 			prepareStatement.setLong(1,?user.getId()); 			prepareStatement.setString(2,?user.getName()); 			prepareStatement.setInt(3,?user.getAge()); 			prepareStatement.execute(); 		 			try?{ 				update(user); 			}?catch?(Exception?e)?{ 				System.out.println("出錯了。。"+e); 				//回滾至保護點 				connection.rollback(saveUser); 			} 			connection.commit(); 			 		}?catch?(SQLException?e)?{ 			e.printStackTrace(); 		}?finally?{ 			try?{ 				connection.close(); 			}?catch?(SQLException?e)?{ 				e.printStackTrace(); 			} 		} 		 		return?true; 	} 	 	public?boolean?update(User?user)?{ 		System.out.println("save?user:"+user); 		 		try?{ 			PreparedStatement?prepareStatement?=?connection.prepareStatement("update?user?set?name?=???,age?=???where?id?=??)"); 			prepareStatement.setLong(3,?user.getId()); 			prepareStatement.setString(1,?"王大拿"); 			prepareStatement.setInt(2,?100/0); 			prepareStatement.execute(); 			 			connection.commit(); 			 		}?catch?(SQLException?e)?{ 			e.printStackTrace(); 		} 		 		return?true; 	} }

以上內容整理若有錯誤請指正,謝謝!

更多Mysql相關問題請訪問PHP中文網:Mysql視頻教程

? 版權聲明
THE END
喜歡就支持一下吧
點贊13 分享