Mybatis中的事物提交commit()方法

本文转至:https://blog.csdn.net/sunroyfcb/article/details/80517945 

Mybatis通过对JDBC进行封装,极大地简化了程序员对数据库的操作,例如对数据库的增删改查操作。其中当进行增删改操作时,都会涉及到用户数据的提交,那么Mybatis中究竟是如何完成数据的提交的呢?这里将对Mybatis中的commit()方法进行简单的剖析,看看底层是如何实现事物提交的。


       其实Mybatis中可以设置自动提交功能。在利用工厂模式获得SqlSession实现类对象时,采用openSession(true),即可实现自动提交,无需调用commit()方法。但是程序是为了现实中的应用场景而产生的,现实中往往采用手动提交的方式,避免误操作,因此通常使用的是openSession()方法,底层获得了一个SqlSession接口的实现类DefaultSqlSession,这是它的构造方法,这里提一句,dirty=false表示该对象中的数据与数据库同步,不是脏数据。
 

public DefaultSqlSession(Configuration configuration, Executor executor, boolean autoCommit) {
    this.configuration = configuration;
    this.executor = executor;
    this.dirty = false;
    this.autoCommit = autoCommit;
}

 通过进入DefaultSqlSession类可以看到,我们进行增删改操作,最终底层都会调用这个类中的update()方法,以下是update()方法:

public int update(String statement, Object parameter) {
    try {
      dirty = true;
      MappedStatement ms = configuration.getMappedStatement(statement);
      return executor.update(ms, wrapCollection(parameter));
    } catch (Exception e) {
      throw ExceptionFactory.wrapException("Error updating database.  Cause: " + e, e);
    } finally {
      ErrorContext.instance().reset();
    }
}

 可以看到dirty=true,这里将修改产生的数据暂时视为脏数据,即未与数据库同步。

    当程序执行到commit()方法,即手动提交数据时,其实调用的是DefaultSqlSession类中的commit(false)方法。

//commit()方法调用过程
public void commit() {
    commit(false);
  }
 
public void commit(boolean force) {
    try {
      executor.commit(isCommitOrRollbackRequired(force));
      dirty = false;
    } catch (Exception e) {
      throw ExceptionFactory.wrapException("Error committing transaction.  Cause: " + e, e);
    } finally {
      ErrorContext.instance().reset();
    }
}

      这个方法的核心是执行器executor调用了commit()方法,先来看看方法内部的参数isCommitOrRollbackRequired(force)方法,这里为或表达式,左边为true直接短路返回true。

private boolean isCommitOrRollbackRequired(boolean force) {
    return (!autoCommit && dirty) || force;
}
public void commit(boolean force) {
    try {
      executor.commit(isCommitOrRollbackRequired(force));
      dirty = false;
    } catch (Exception e) {
      throw ExceptionFactory.wrapException("Error committing transaction.  Cause: " + e, e);
    } finally {
      ErrorContext.instance().reset();
    }
}

        因此执行器执行的方法是commit(true),执行完之后将dirty重新改为false,因为数据已经与数据库同步,不再是脏数据。通过调试可以知道,这里的executor是Executor接口实现类CachingExecutor的对象:

public void commit(boolean required) throws SQLException {
    delegate.commit(required);
    tcm.commit();
}

   这里首先进行了清空缓存和刷新数据,然后进行的事物提交,即transaction.commit(),这里的transaction是Transaction接口实现类JdbcTransaction的对象,进入到这个类中,

public void commit() throws SQLException {
    if (connection != null && !connection.getAutoCommit()) {
      if (log.isDebugEnabled()) {
        log.debug("Committing JDBC Connection [" + connection + "]");
      }
      connection.commit();
    }
}

        可以看到底层调用的依然是java基础api中的Connection中的commit方法,这也再一次证明了Mybatis框架实际上是对Jdbc的封装。

你可能感兴趣的:(事务)