一、获取sqlsession

Sqlsession中包含了Configuration对象,可以拿到全局配置信息。
org.apache.ibatis.session.defaults.DefaultSqlSessionFactory#openSession()

public SqlSession openSession() {
        return this.openSessionFromDataSource(this.configuration.getDefaultExecutorType(), (TransactionIsolationLevel)null, false);
    }
二、获取执行器
public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
        executorType = executorType == null ? this.defaultExecutorType : executorType;
        executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
        Object executor;
        if (ExecutorType.BATCH == executorType) {
            executor = new BatchExecutor(this, transaction);
        } else if (ExecutorType.REUSE == executorType) {
            executor = new ReuseExecutor(this, transaction);
        } else {
            executor = new SimpleExecutor(this, transaction);
        }

        if (this.cacheEnabled) {
            executor = new CachingExecutor((Executor)executor);
        }

        Executor executor = (Executor)this.interceptorChain.pluginAll(executor);
        return executor;
    }

执行器分为两大类:一类是CacheExecutor,另一类是普通Executor。
普通Executor又有三种实现:
(1)simpleExecutor:每执行一次update或者select,就开启一个Statement对象,用完就立刻关闭Statement对象。
(2)ReuseExecutor:执行update或者select操作,以sql作为key查找statement对象,存在就重复利用,不存在就存入map中。
(3)BatchExecutor:将所有的sql都添加在批处理对象中,等待统一执行,它缓存了多个Statement对象,等待executeBatch()批处理。

CacheExecutor封装了普通Executor,区别是查询前会先查询缓存中是否有结果,如果缓存中有就从缓存中拿,没有的话,使用普通executor执行,再把结果放入缓存中。

三、获取mapper

org.apache.ibatis.session.defaults.DefaultSqlSession#getMapper

public <T> T getMapper(Class<T> type) {
        return this.configuration.getMapper(type, this);
    }

由于mapper是一个接口所以会生成一个动态代理类。

 public static <T> T newMapperProxy(Class<T> mapperInterface, SqlSession sqlSession) {
        ClassLoader classLoader = mapperInterface.getClassLoader();
        Class<?>[] interfaces = new Class[]{mapperInterface};
        MapperProxy proxy = new MapperProxy(sqlSession);
        return Proxy.newProxyInstance(classLoader, interfaces, proxy);
    }
四、mapper的调用

执行代理后的execute方法,根据mapper.xml中配置的操作标签类型,执行对象的sqlsession的增删改查方法。

public Object execute(Object[] args) {
        Object result = null;
        Object param;
        if (SqlCommandType.INSERT == this.type) {
            param = this.getParam(args);
            result = this.sqlSession.insert(this.commandName, param);
        } else if (SqlCommandType.UPDATE == this.type) {
            param = this.getParam(args);
            result = this.sqlSession.update(this.commandName, param);
        } else if (SqlCommandType.DELETE == this.type) {
            param = this.getParam(args);
            result = this.sqlSession.delete(this.commandName, param);
        } else {
            if (SqlCommandType.SELECT != this.type) {
                throw new BindingException("Unknown execution method for: " + this.commandName);
            }

            if (this.returnsVoid && this.resultHandlerIndex != null) {
                this.executeWithResultHandler(args);
            } else if (this.returnsList) {
                result = this.executeForList(args);
            } else if (this.returnsMap) {
                result = this.executeForMap(args);
            } else {
                param = this.getParam(args);
                result = this.sqlSession.selectOne(this.commandName, param);
            }
        }

        return result;
    }

sqlsession底层会调用executor的增删改查方法,这里以update方法为例。

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

        return var4;
    }

实际调用的是simpleExecutor的doUpdate方法

public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
        Statement stmt = null;

        int var6;
        try {
            Configuration configuration = ms.getConfiguration();
            StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, (ResultHandler)null);
            stmt = this.prepareStatement(handler);
            var6 = handler.update(stmt);
        } finally {
            this.closeStatement(stmt);
        }

        return var6;
    }

然后是调用PreparedStatementHandler类中的方法,有点类似于我们直接jdbc的调用写法了。

 public int update(Statement statement) throws SQLException {
        PreparedStatement ps = (PreparedStatement)statement;
        ps.execute();
        int rows = ps.getUpdateCount();
        Object parameterObject = this.boundSql.getParameterObject();
        KeyGenerator keyGenerator = this.mappedStatement.getKeyGenerator();
        keyGenerator.processAfter(this.executor, this.mappedStatement, ps, parameterObject);
        return rows;
    }

query的调用更能说明问题:

public List query(Statement statement, ResultHandler resultHandler) throws SQLException {
        PreparedStatement ps = (PreparedStatement)statement;
        ps.execute();
        return this.resultSetHandler.handleResultSets(ps);
    }

总结:其实就是对jdbc的层层封装和功能完善。