2023-07-19 10:23:49 +08:00

4.0 KiB
Raw Blame History

事务管理

MyBatis-Flex 提供了一个名为 Db.tx() 的方法,用于进行事务管理,若使用 Spring 框架的场景下,也可使用 @Transactional 注解进行事务管理。

Db.tx() 方法定义如下:

boolean tx(Supplier<Boolean> supplier);
boolean tx(Supplier<Boolean> supplier, Propagation propagation);

<T> T txWithResult(Supplier<T> supplier);
<T> T txWithResult(Supplier<T> supplier, Propagation propagation);

方法:

  • tx返回结果为 Boolean返回 null 或者 false 或者 抛出异常,事务回滚
  • txWithResult返回结果由 Supplier 参数决定,只有抛出异常时,事务回滚

参数:

  • supplier:要执行的内容(代码)
  • propagation:事务传播属性

事务传播属性 propagation 是一个枚举类,其枚举内容如下:

//若存在当前事务,则加入当前事务,若不存在当前事务,则创建新的事务
REQUIRED(0),

//若存在当前事务,则加入当前事务,若不存在当前事务,则已非事务的方式运行
SUPPORTS(1),

//若存在当前事务,则加入当前事务,若不存在当前事务,则抛出异常
MANDATORY(2),

//始终以新事务的方式运行,若存在当前事务,则暂停(挂起)当前事务。
REQUIRES_NEW(3),

//以非事务的方式运行,若存在当前事务,则暂停(挂起)当前事务。
NOT_SUPPORTED(4),

//以非事务的方式运行,若存在当前事务,则抛出异常。
NEVER(5),

//暂时不支持
NESTED(6),

Db.tx() 代码示例:

Db.tx(() -> {

    //进行事务操作

    return true;
});

tx() 方法抛出异常,或者返回 false或者返回 null则回滚事务。只有正常返回 true 的时候,进行事务提交。

嵌套事务

示例代码:

Db.tx(() -> {

    //进行事务操作

    boolean success = Db.tx(() -> {
        //另一个事务的操作
        return true;
    });


    return true;
});

支持无限极嵌套,默认情况下,嵌套事务直接的关系是:REQUIRED(若存在当前事务,则加入当前事务,若不存在当前事务,则创建新的事务)。

@Transactional

MyBatis-Flex 已支持 Spring 框架的 @Transactional,在使用 SpringBoot 的情况下,可以直接使用 @Transactional 进行事务管理。 同理,使用 Spring 的 TransactionTemplate 进行事务管理也是没问题的。

注意:若项目未使用 SpringBoot只用到了 Spring需要参考 MyBatis-Flex 的 FlexTransactionAutoConfiguration 进行事务配置,才能正常使用 @Transactional 注解。

特征

  • 1、支持嵌套事务
  • 2、支持多数据源

注意在多数据源的情况下所有数据源的数据库请求Connection会执行相同的 commit 或者 rollback但并非原子操作。例如

@Transactional
public void doSomething(){

    try{
        DataSourceKey.use("ds1");
        Db.updateBySql("update ....");
    }finally{
        DataSourceKey.clear()
    }

    try{
        DataSourceKey.use("ds2");
        Db.updateBySql("update ...");
    }finally{
        DataSourceKey.clear()
    }

    //抛出异常
    int x = 1/0;
}

在以上的例子中,两次 Db.update(...) 虽然是两个不同的数据源,但它们都在同一个事务 @Transactional 里,因此,当抛出异常的时候, 它们都会进行回滚rollback

以上提到的 并非原子操作,指的是:

假设在回滚的时候,恰好其中一个数据库出现了异常(比如 网络问题数据库崩溃此时可能只有一个数据库的数据正常回滚rollback。 但无论如何MyBatis-Flex 都会保证在同一个 @Transactional 中的多个数据源,保持相同的 commit 或者 rollback 行为。