@Transactional 事务隔离级别

130 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

1.@Transactional

描述单个方法或类上的事务属性: image.png

  • 在类上 此注释作为默认值应用于声明类及其子类的所有方法(但若他是父类,他子类则不会有这个事务控制)
  • 在方法上,就是应用于该注释的方法

一般我们在什么时候会用这个注释呢? 先看一段mybatis-plus中saveBatch(Collection entityList)源码,其大致的意思就是遍历每个分组把数据存入数据库 当我们直接调用saveBatch方法是 他其实已经做了事务操作

@Transactional(
    rollbackFor = {Exception.class}
)
public boolean saveBatch(Collection<T> entityList, int batchSize) {
    String sqlStatement = this.sqlStatement(SqlMethod.INSERT_ONE);
    SqlSession batchSqlSession = this.sqlSessionBatch();
    Throwable var5 = null;

    try {
        int i = 0;

        for(Iterator var7 = entityList.iterator(); var7.hasNext(); ++i) {
            T anEntityList = var7.next();
            batchSqlSession.insert(sqlStatement, anEntityList);
            if (i >= 1 && i % batchSize == 0) {
                batchSqlSession.flushStatements();
            }
        }

        batchSqlSession.flushStatements();
        return true;
    } catch (Throwable var16) {
        var5 = var16;
        throw var16;
    } finally {
        if (batchSqlSession != null) {
            if (var5 != null) {
                try {
                    batchSqlSession.close();
                } catch (Throwable var15) {
                    var5.addSuppressed(var15);
                }
            } else {
                batchSqlSession.close();
            }
        }

    }
}

从这上面 我们其实可以得到启示,假设我们在一个方法中设计到多条数据的操作或者多张表格的联表操作 这是最好加上事务注释,以保证原子性操作

2. 事务隔离级别

主要有4种隔离级别

  • 读未提交 此隔离级别,事务可以看到未提交的事务执行的结果。这就可能出现脏读
  • 读已提交 此级别智能读已经提交的内容,这个级别可以避免脏读,但是不可重复读(不可重复读可以理解为在一个事务范围内多次查询但由于在这个过程,数据被另外的事务修改了,则返回的结果不同)
  • 可重读 在事务执行期间会锁定该事务以任何方式引用的所有行,保证在一个事务中查询的数据都是同一个结果,可以解决不可重复读,但会出现幻读
  • 可串行化 最高级别,通过事务排序,这样是不会产生冲突,从而解决幻读。(就好像加了一把锁,只有拿到那把锁才能操作,完了就释放锁给下一个事务)

我们可以看到@Transactional 默认的隔离级别

image.png Isolation.DEFAULT 是为默认数据源的级别,我使用的是mysql 则mysql默认的隔离级别是 可重读