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

       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();
}

而CachingExecutor可以看成是SimpleExecutor类的一个装饰类,主要作用是在SimpleExecutor加一个缓冲区。因此delegate实际上SimpleExecutor类的对象,调用的自然是本类的commit()方法:

public void commit(boolean required) throws SQLException {
    if (closed) throw new ExecutorException("Cannot commit, transaction is already closed");
    clearLocalCache();
    flushStatements();
    if (required) {
      transaction.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的封装。

  • 9
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
MyBatis批量提交数据的方法是使用`BatchExecutor`批量执行SQL语句。具体步骤如下: 1. 在`SqlSessionFactory`配置`ExecutorType`为`BATCH`,即使用`BatchExecutor`。 ```xml <configuration> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource> <mapper resource="com/example/mapper/UserMapper.xml"/> </environment> </environments> <mappers> <mapper resource="com/example/mapper/UserMapper.xml"/> </mappers> </configuration> ``` 2. 在Mapper接口定义批量插入方法,使用`@Param`注解指定参数名。 ```java public interface UserMapper { void insertUsers(@Param("users") List<User> users); } ``` 3. 在Mapper XML文件编写批量插入SQL语句。 ```xml <insert id="insertUsers" parameterType="java.util.List"> insert into user(name, age) values <foreach collection="users" item="user" separator=","> (#{user.name}, #{user.age}) </foreach> </insert> ``` 4. 在调用批量插入方法时,使用`SqlSession`的`flushStatements`方法刷新缓存并执行批量操作。 ```java List<User> users = new ArrayList<>(); // 添加多个User对象到users列表 try (SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH)) { UserMapper userMapper = sqlSession.getMapper(UserMapper.class); for (User user : users) { userMapper.insertUser(user); } sqlSession.flushStatements(); sqlSession.commit(); } ``` 以上就是MyBatis批量提交数据的方法

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值