MyBatis学习(二)之运行流程初识

    到底和数据库交互一次,MyBatis都是怎么样来处理请求然后和数据库交互再返回给调用者的呢?也就是说MyBatis具体的运行流程是怎样的呢?
    这里主要跟踪查询,以SqlSession.<E> List<E> selectList(String statement)为入口进行跟踪。这里的statement就是映射的sql语句的id。

    首先加载xml配置文件,然后通过SqlSessionFactoryBuilder构造SqlSessionFactory.
    获取SqlSession,我们采用默认的获取方式:
    SqlSession sqlSessionWithXml = sessionFactory.openSession();    

    public SqlSession openSession() {
        return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
     }

   openSessionFromDataSource方法源码:
 
   /**
     * 从数据源中获取SqlSession
     * @param execType 执行类型 SIMPLE, REUSE, BATCH
     * @param level 数据库事务隔离级别
     * @param autoCommit 是否自动提交
     * @return
     */
    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);
            final Executor executor = configuration.newExecutor(tx, execType, autoCommit);//获取数据库交互命令执行器
            return new DefaultSqlSession(configuration, executor);
        } 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();
        }
    }


    这里基本都是由配置文件的信息加载的,主要注意下newExecutor这个方法:
    
    newExecutor主要根据不同的executorType实例化不同的执行器,包括批量执行器、简单执行器、复用执行器以及缓存执行器

    调用selectList(String statement) 最终会调用selectList(String statement, Object parameter, RowBounds rowBounds)这个方法,如下图所示:
    

关于这个方法具体的解释如下:
   /**
     * @param statement 映射语句的id
     * @param parameter 查询传入的参数
     * @param rowBounds 结果行数限制,由于我们没有自定义RowBounds,所以使用其默认值,即0开始到Integer.MAX_VALUE条记录
     * @param <E>
     * @return
     */
    public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
        try {
            //根据statement获取已映射的sql语句
            MappedStatement ms = configuration.getMappedStatement(statement);
           
            //使用Executor执行器来执行查询
            List<E> result = executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
            return result;
        } catch (Exception e) {
            throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e);
        } finally {
            ErrorContext.instance().reset();
        }
    }

这里可以看到主要分为两个步骤,第一是根据statement参数得到相应的映射语句,然后将查询工作交予Executor来执行。
  • 首先我们看看是如何获取到对应的映射语句的
                
                这里的mappedStatements是一个MyBatis自定义的Map类型StrictMap,里面的数据是在加载配置初始化Configuration添加。
  •     Executor执行查询命令
                

然后跳转到queryFromDatabase--> doQuery:


 现在查询流程已经交予StatementHandler的query方法处理了,我们来看看StatementHandler的处理流程:
 public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
    PreparedStatement ps = (PreparedStatement) statement;
    ps.execute();
    return resultSetHandler.<E> handleResultSets(ps);
 }

逻辑很简单,直接执行Statement,然后将结果交由ResultHandler处理:

ResultHandler也是MyBatis的一个拦截点 , 用于处理数据库返回结果的封装。结果处理过程中,还有一个扩展点,ObjectWrapper 和 ObjectWrapperFactory, 用于自定义返回类型的处理逻辑处理。由于我们这里并没有使用任何的自定义类型处理,所以暂时忽略这个扩展。
ResultHandler将结果封装后,返回给查询调用。即完成了一次MyBatis与数据库的交互。整个交互的流程大致如下:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值