一、transactiontemplate用法
TransactionTemplate
是 Spring 的一個功能強大的事務管理工具類。它為我們帶來了很多便利,通過它我們可以不用再關心事務的傳播性和隔離級別等一系列細節,而是把精力放在業務邏輯的實現上。使用 TransactionTemplate
可以讓代碼更加簡潔、優雅和安全。
使用 TransactionTemplate
的方式非常簡單,只需要在需要進行事務管理的代碼塊外層套一個 execute
方法就可以開啟事務了,這個方法會隱式的開啟一個事務,如果 execute
方法內部的代碼執行成功,則事務會自動提交,否則事務會自動回滾。
public interface TransactionTemplate {
<T> T execute(TransactionCallback<T> action) throws TransactionException;
}
其中,TransactionCallback
接口的 doInTransaction
方法就是需要進行事務管理的代碼塊。這個接口包含一個泛型參數 T
,表示執行結果的類型,這個類型的值會被 execute
方法返回。
public interface TransactionCallback<T> {
T doInTransaction(TransactionStatus status);
}
通常情況下,我們需要在 doInTransaction
方法內部寫上具體的業務邏輯代碼。例如,在下面的示例中,我們採用了匿名內部類方式實現了一個 TransactionCallback
。
public class UserServiceImpl implements UserService {
private final TransactionTemplate transactionTemplate;
public UserServiceImpl(DataSource dataSource) {
this.transactionTemplate = new TransactionTemplate(new DataSourceTransactionManager(dataSource));
}
public void transferMoney(String fromUser, String toUser, int money) {
transactionTemplate.execute(new TransactionCallback<Void>() {
public Void doInTransaction(TransactionStatus status) {
try {
User from = userDao.findByName(fromUser);
User to = userDao.findByName(toUser);
from.setMoney(from.getMoney() - money);
to.setMoney(to.getMoney() + money);
userDao.update(from);
userDao.update(to);
return null;
} catch (Exception e) {
status.setRollbackOnly();
throw e;
}
}
});
}
}
在上面的 transferMoney
方法中,我們使用了 TransactionTemplate
來控制事務,從而實現了轉賬的功能。事務的傳播性、超時時間、隔離級別等信息都可以在 TransactionTemplate
中進行配置。
二、transactionTemplate 回滾
事務處理中,有時候我們需要手動回滾一個事務,例如某些必要的校驗未通過,或者拋出了某個異常。 TransactionTemplate
為我們提供了很方便的事務回滾機制。
要實現事務回滾,我們只需要在 TransactionCallback
的 doInTransaction
方法內部拋出一個運行時異常即可,例如下面的示例:
transactionTemplate.execute(new TransactionCallback<Void>() {
public Void doInTransaction(TransactionStatus status) {
try {
[...]
if (someCheckFailed) {
throw new RuntimeException("校驗未通過,回滾事務");
}
[...]
} catch (Exception e) {
status.setRollbackOnly();
throw e;
}
}
});
在這個示例中,如果檢測到校驗未通過,就會拋出一個運行時異常,這時候 TransactionTemplate
會自動回滾事務,保證不會出現數據不一致等問題。
三、transactionTemplate 拿返回值
在實際業務應用中,我們不僅需要對事務進行控制,還需要返回一些數據給調用者。 TransactionTemplate
也為我們提供了很方便的方式來拿到執行結果。
在 TransactionCallback
的 doInTransaction
方法中,我們可以直接返回一個數據對象,這個數據對象的類型需要和 execute
方法的泛型類型參數 T
一致。例如:
String result = transactionTemplate.execute(new TransactionCallback<String>() {
public String doInTransaction(TransactionStatus status) {
try {
[...]
String someResult = someService.doSomething();
[...]
return someResult;
} catch (Exception e) {
status.setRollbackOnly();
throw e;
}
}
});
在這個示例中,我們通過返回一個 String
類型的結果來演示如何拿到執行結果。
四、transactionTemplate 隔離級別
在多線程環境下,當多個事務並發執行的時候,可能會出現數據不一致的問題。這時候,事務的隔離級別就非常重要了,它定義了事務之間的可見性和並發性。Spring 的 TransactionTemplate
為我們提供了五種隔離級別,我們可以根據實際業務場景來選擇合適的隔離級別。
五種隔離級別分別為:
ISOLATION_DEFAULT
:使用底層數據庫的默認隔離級別,通常為ISOLATION_READ_COMMITTED
。ISOLATION_READ_UNCOMMITTED
:讀取未提交數據。ISOLATION_READ_COMMITTED
:只能讀取已提交數據。ISOLATION_REPEATABLE_READ
:可重複讀,事務執行期間,不能修改已讀取的數據。ISOLATION_SERIALIZABLE
:串行化,所有事務按照順序依次執行。
我們可以在 TransactionTemplate
中使用 setIsolationLevel
方法來指定隔離級別,例如:
TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_READ_UNCOMMITTED);
transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
transactionTemplate.setTimeout(30);
在這個示例中,我們將事務的隔離級別設置為 ISOLATION_READ_UNCOMMITTED
,意味着可以讀取未提交的數據。同時,我們還定義了事務的傳播行為為 PROPAGATION_REQUIRED
,超時時間為 30 秒。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/237099.html