Solon詳解(四)- Solon的事務傳播機制

Solon詳解系列文章:
Solon詳解(一)- 快速入門
Solon詳解(二)- Solon的核心
Solon詳解(三)- Solon的web開發
Solon詳解(四)- Solon的事務傳播機制
Solon詳解(五)- Solon擴展機制之Solon Plugin
Solon詳解(六)- Solon的校驗擴展框架使用與擴展 html

在前面的篇章裏咱們已經見識了 Solon 對事務的控制,及其優雅曼妙的身姿。該篇將對事務進行詳解。出於對用戶的學習成本考慮,Solon 借簽了Spring 的事務傳播策略;因此體驗上幾乎同樣。java

1、爲何要有傳播機制?

Solon 對事務的控制,是使用 aop 切面實現的,因此不用關心事務的開始,提交 ,回滾,只須要在方法上加 @XTran 註解便可。web

這時候就容易產生一些疑問:併發

  • 場景一:classA 方法調用了 classB 方法,但兩個方法都有事務
    • 這個時候若是 classB 方法異常,是讓 classB 方法提交,仍是兩個一塊兒回滾?
  • 場景二:classA 方法調用了 classB 方法,可是隻有 classA 方法加了事務
    • 是否把 classB 也加入 classA 的事務,若是 classB 異常,是否回滾 classA?
  • 場景三:classA 方法調用了 classB 方法,二者都有事務,classB 已經正常執行完,但 classA 異常
    • 是否須要回滾 classB 的數據?

這個時候事務的傳播機制和策略就派上用場了app

2、傳播機制生效條件

由於 Solon 是使用 aop 來代理事務控制 ,是針對於接口或類的,因此在同一個類中兩個方法的調用,傳播機制是不生效的框架

3、傳播機制的策略

下面的類型都是針對於被調用方法來講的,理解起來要想象成兩個 class 方法的調用才能夠。學習

傳番策略 說明
TranPolicy.required 支持當前事務,若是沒有則建立一個新的。這是最多見的選擇。也是默認。
TranPolicy.requires_new 新建事務,若是當前存在事務,把當前事務掛起。
TranPolicy.nested 若是當前有事務,則在當前事務內部嵌套一個事務;不然新建事務。
TranPolicy.mandatory 支持當前事務,若是沒有事務則報錯。
TranPolicy.supports 支持當前事務,若是沒有則不使用事務。
TranPolicy.not_supported 以無事務的方式執行,若是當前有事務則將其掛起。
TranPolicy.never 以無事務的方式執行,若是當前有事務則報錯。

4、事務的隔離級別

屬性 說明
unspecified 默認(JDBC默認)
read_uncommitted 髒讀:其它事務,可讀取未提交數據
read_committed 只讀取提交數據:其它事務,只能讀取已提交數據
repeatable_read 可重複讀:保證在同一個事務中屢次讀取一樣數據的結果是同樣的
serializable 可串行化讀:要求事務串行化執行,事務只能一個接着一個地執行,不能併發執行

5、@XTran 屬性說明

屬性 說明
policy 事務傳導策略
isolation 事務隔離等級
readOnly 是否爲只讀事務

6、示例

  • 父回滾,子回滾
@XService
public class UserService{
    @XTran
    public void addUser(UserModel user){
        //....
    }
}

@XController
public class DemoController{
    @XInject
    UserService userService; 
    
    //父回滾,子回滾
    //
    @XTran
    @XMapping("/user/add2")
    pubblic void addUser2(UserModel user){
        userService.addUser(user); 
        throw new RuntimeException("不讓你加");
    }
}
  • 父回滾,子不回滾
@XService
public class UserService{
    @XTran(policy = TranPolicy.requires_new)
    public void addUser(UserModel user){
        //....
    }
}

@XController
public class DemoController{
    @XInject
    UserService userService; 
    
    //父回滾,子不回滾
    //
    @XTran
    @XMapping("/user/add2")
    pubblic void addUser2(UserModel user){
        userService.addUser(user); 
        throw new RuntimeException("不讓你加;但仍是加了:(");
    }
}
  • 子回滾父不回滾
@XService
public class UserService{
    @XTran(policy = TranPolicy.nested)
    public void addUser(UserModel user){
        //....
        throw new RuntimeException("不讓你加");
    }
}

@XController
public class DemoController{
    @XInject
    UserService userService; 
    
    //子回滾父不回滾
    //
    @XTran
    @XMapping("/user/add2")
    pubblic void addUser2(UserModel user){
        try{
            userService.addUser(user); 
        }catch(ex){ }
    }
}
  • 多數據源事務示例
@XService
public class UserService{
    @Db("db1")
    UserMapper userDao;
    
    @XTran
    public void addUser(UserModel user){
        userDao.insert(user);
    }
}

@XService
public class AccountService{
    @Db("db2")
    AccountMappeer accountDao;

    @XTran
    public void addAccount(UserModel user){
        accountDao.insert(user);
    }
}

@XController
public class DemoController{
    @XInject
    AccountService accountService; 
    
    @XInject
    UserService userService; 
    
    @XTran
    @XMapping("/user/add")
    pubblic void addUser(UserModel user){
        userService.addUser(user);     //會執行db1事務
        
        accountService.addAccount(user);    //會執行db2事務
    }
}
相關文章
相關標籤/搜索