浅谈Mybatis中的事务提交Commit()方法

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

数据插入示例

其实Mybatis中可以设置自动提交功能。在利用工厂模式获得SqlSession实现类对象时,采用openSession(true),即可实现自动提交,无需调用commit()方法。
代码:
创建sqlsession方法(放在工具类里使用)

   /**
      * @Description:  获取sqlsession
      * @param sqlMapConfgi.xml 输入流
      * @return  sqlSession
      * @throws
      * @author 康世行
      * @date 2021-07-09 11:04
      */
    public static SqlSession createSqlSession(InputStream resourcesAsStram){
        //创建sqlSessionFactory工厂
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder=new SqlSessionFactoryBuilder();
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(resourcesAsStram);
        return sqlSessionFactory.openSession(true);//根据SqlSeesion工厂创建SqlSeesion
    }

测试代码

   /**
          * @Description: 保存用户
          * @param
          * @return ${return_type}
          * @throws
          * @author 康世行
          * @date 2021-07-09 11:40
          */
        @Test
    public void InsertTest() throws IOException {
        //读取配置文件
        InputStream resourceAsStream = Resources.getResourceAsStream("SqMapConfig1.xml");
        //获取sqlSession
        SqlSession sqlSession = MydatisUtil.createSqlSession(resourceAsStream);
        //获取代理对象
        IUserDao userDao = sqlSession.getMapper(IUserDao.class);
        //实例化实体
        User user=new User();
        user.setAddress("廊坊");
        user.setSex("男");
        user.setUsername("dfasd");
        user.setBirthday(new Date());
            System.out.println("保存之前"+user);
        //获取保存用户方法
        int i = userDao.saveUser(user);
            System.out.println(i);
        if(i==0){
            System.out.println("保存失败!");
        }else {
            System.out.println("保存成功!");
        }
            System.out.println("保存之后 "+user);
  
    }

结果:
在这里插入图片描述

源码分析

但是程序是为了现实中的应用场景而产生的,现实中往往采用手动提交的方式,避免误操作,因此通常使用的是openSession()方法。

dirty

底层获得了一个SqlSession接口的实现类DefaultSqlSession,这是它的构造方法,这里提一句,dirty=false表示该对象中的数据与数据库同步,不是脏数据。改成true就是不与数据库同步,暂时标记为脏数据。

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

commit()

//提交事务
sqlSession.commit();

在这里插入图片描述
SqlSession 接口
在这里插入图片描述

可以在SqlSession接口里看到有两个commit方法,一个是无参数和一个有参数的。
无参数的那个就是我们使用的手动提交事务的方法,有参数的我们传递TRUE进去,就可以不使用手动提交了。可以进行自动提交事务(这样不太安全,不推荐使用)

sqlSession.commit() 里调用DefaulttSqlSession 类里有参数的commit方法,赋值一个默认值 FALSE。 就取消了事务的自动提交!
//无参数


    public void commit() {
        this.commit(false);
    }
   

//有参数


    public void commit(boolean force) {
        try {
            //调用Executor的commit方法进行提交事务
            //
            this.executor.commit(this.isCommitOrRollbackRequired(force));
            //表示数据与数据库同步,不是脏数据
            this.dirty = false;
        } catch (Exception var6) {
            throw ExceptionFactory.wrapException("Error committing transaction.  Cause: " + var6, var6);
        } finally {
            ErrorContext.instance().reset();
        }

    }

//这个方法里返回TRUE
this.isCommitOrRollbackRequired(force)

  private boolean isCommitOrRollbackRequired(boolean force) {
        return !this.autoCommit && this.dirty || force;
    }

使用的是或的逻辑,左边或者右边任意一个成立都会返回TRUE
this.executor.commit(true); //这就是把this.isCommitOrRollbackRequired(force)方法返回的TRUE赋值给 executor的commit方法。
this.dirty=false;表示数据与数据库同步,不是脏数据。 到此刻数据提交成功!

类的调用关系

Executtor //执行器

DefaulttSqlSession void commit void commit Executor void commit BaseExecutor void commit Transaction void commit JdbcTransaction void commit Connection

Defaultsqlsession类里还包含了,增删改查的方法

在这里插入图片描述
在这里插入图片描述

posted @ 2021-07-10 19:50  康世行  阅读(907)  评论(0编辑  收藏  举报