Mybatis源码--SqlSessionFactory&SqlSession源码分析

1 概述

这两个类,SqlSessionFactory作为Mybatis的入口提供了各种获取SqlSession的函数。SqlSessionFactory大部分情况下生成唯一的实例,读写分离和多数据库除外。SqlSession主要用于提供CRUD操作。

2 SqlSessionFactory

我们来看一下SqlSessionFactory的源码。

public interface SqlSessionFactory {

  SqlSession openSession();

  SqlSession openSession(boolean autoCommit);
  SqlSession openSession(Connection connection);
  SqlSession openSession(TransactionIsolationLevel level);

  SqlSession openSession(ExecutorType execType);
  SqlSession openSession(ExecutorType execType, boolean autoCommit);
  SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level);
  SqlSession openSession(ExecutorType execType, Connection connection);

  Configuration getConfiguration();

}

通过上面的源码我们可以发现SqlSessionFactory的作用主要是通过是否自动提交、事务的隔离级别、数据库连接或者执行器类型等来创建SqlSession的。
在这里针对器其现类,我们仅仅看一下DefaultSqlSessionFactory,因为另一个实现类SqlSessionManager官方已经不建议使用了,这里我也就不深入分析了。
当然根据抽象工厂函数设计模式的作用我们可以猜想这个DefaultSqlSessionFactory的作用是用于创建DefaultSqlSession的。
查看DefaultSqlSessionFactory的源码实现,可以看见DefaultSqlSessionFactory对SqlSessionFactory中的函数的实现都是依赖于openSessionFromDataSource和openSessionFromConnection函数的。

(1)openSessionFromDataSource函数

private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
        Transaction tx = null;
        try {

            //获取环境对象		
            final Environment environment = configuration.getEnvironment();

            //获取事务对象(这里再次使用了抽象工厂的设计模式)
            final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
            tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);

            //初始化执行器(Mapper文件的sql语句都是通过其执行的)
            final Executor executor = configuration.newExecutor(tx, execType);

            //初始化并返回DefaultSqlSession对象
            return new DefaultSqlSession(configuration, executor, autoCommit);
        } catch (Exception e) {
            closeTransaction(tx); // may have fetched a connection so lets call close()
            throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);
        } finally {
            ErrorContext.instance().reset();
        }
    }

(2)openSessionFromConnection函数

private SqlSession openSessionFromConnection(ExecutorType execType, Connection connection) {
        try {
            boolean autoCommit;
            try {
                autoCommit = connection.getAutoCommit();
            } catch (SQLException e) {
                autoCommit = true;
            }
            final Environment environment = configuration.getEnvironment();
            final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
            final Transaction tx = transactionFactory.newTransaction(connection);
            final Executor executor = configuration.newExecutor(tx, execType);
            return new DefaultSqlSession(configuration, executor, autoCommit);
        } catch (Exception e) {
            throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);
        } finally {
            ErrorContext.instance().reset();
        }
    }

上面两个方法的区别就在于生成事务对象的时候传入的参数不同,一个是依赖于DataSource对象,一个是依赖于Connection对象。如果是openSessionFromDataSource,我们可以看见,最终在调用openConnection函数创建连接的时候依然会通过dataSource来获取到Connection。

@Override
public Connection getConnection() throws SQLException {

    //如果Connection不能存在则通过DataSource创建Connection
    if (connection == null) {
        openConnection();
    }
        return connection;
}

protected void openConnection() throws SQLException {
    if (log.isDebugEnabled()) {
        log.debug("Opening JDBC Connection");
    }
    connection = dataSource.getConnection();
    if (level != null) {
        connection.setTransactionIsolation(level.getLevel());
    }
    setDesiredAutoCommit(autoCommmit);
}

3 SqlSession

这个是使用Mybatis的接口,通过这个接口我们可以执行SQL命令、管理事务和获取到Mapper对象。
针对这个类的数据库CRUD方法我们仅仅看看两个基本的方法就行,因为其余的方法都是基于这两个方法执行的。

    @Override
    public void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler) {
        try {

            //获取到Mapper文件的sql语句块封装对象	
            MappedStatement ms = configuration.getMappedStatement(statement);

            //最终调用Executor的query函数,针对Executor的分析我们前面已经提到
            executor.query(ms, wrapCollection(parameter), rowBounds, handler);
        } catch (Exception e) {
            throw ExceptionFactory.wrapException("Error querying database.  Cause: " + e, e);
        } finally {
            ErrorContext.instance().reset();
        }
    }

    @Override
    public int update(String statement, Object parameter) {
        try {
            dirty = true;
            //获取到Mapper文件的sql语句块封装对象
            MappedStatement ms = configuration.getMappedStatement(statement);

            //最终调用Executor的update函数,针对Executor的分析我们前面已经提到
            return executor.update(ms, wrapCollection(parameter));
        } catch (Exception e) {
            throw ExceptionFactory.wrapException("Error updating database.  Cause: " + e, e);
        } finally {
            ErrorContext.instance().reset();
        }
    }

上面就是对SqlSessionFactory和SqlSession的分析,下面我们将使用一篇文章来分析Mybatis中SQL执行的整个过程。欢迎交流。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值