MyBatis源码探索

  

  每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为中心的。SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder 获得。而 SqlSessionFactoryBuilder 则可以从 XML (mybatis-config.xml) 配置文件或一个预先定制的 Configuration 的实例构建出 SqlSessionFactory 的实例。

类图

其中SqlSession是比较重要的接口,提供基本的方法,比如:sql语句、事务等操作;

具体执行过程以<E> List<E> selectList(String statement);方法为例:SqlSession的实现类DefaultSqlSession调用configuration.getMappedStatement(statement);获取statement节点的sql,存放在MappedStatement,传给接口Executor的query方法。

 1   @Override
 2   public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
 3     try {
 4       MappedStatement ms = configuration.getMappedStatement(statement);
 5       return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
 6     } catch (Exception e) {
 7       throw ExceptionFactory.wrapException("Error querying database.  Cause: " + e, e);
 8     } finally {
 9       ErrorContext.instance().reset();
10     }
11   }

Executor处理MappedStatement的关键代码和注释如下

 1   // 是否需要刷新缓存
 2   if (queryStack == 0 && ms.isFlushCacheRequired()) {
 3       clearLocalCache();
 4     }
 5     List<E> list;
 6     try {
 7       queryStack++;
 8       list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;
 9       if (list != null) {
10         // 如果缓存中有数据,直接拿到缓存中的数据
11         handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
12       } else {
13         // 否则从数据库中获取
14         list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
15       }
16     } finally {
17       queryStack--;
18     }
 1   private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
 2     List<E> list;
 3     localCache.putObject(key, EXECUTION_PLACEHOLDER);
 4     try {
 5       list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
 6     } finally {
 7       localCache.removeObject(key);
 8     }
 9     // 把查询结果放入缓存后返回结果list
10     localCache.putObject(key, list);
11     if (ms.getStatementType() == StatementType.CALLABLE) {
12       localOutputParameterCache.putObject(key, parameter);
13     }
14     return list;
15   }
 1   @Override
 2   public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
 3     // 用来执行静态sql语句的对象
 4     Statement stmt = null;
 5     try {
 6       Configuration configuration = ms.getConfiguration();
 7       StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
 8       stmt = prepareStatement(handler, ms.getStatementLog());
 9       // StatementHandler中处理sql的执行和结果的返回
10       return handler.<E>query(stmt, resultHandler);
11     } finally {
12       closeStatement(stmt);
13     }
14   }
1   @Override
2   public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
3     String sql = boundSql.getSql();
4     statement.execute(sql);
5     return resultSetHandler.<E>handleResultSets(statement);
6   }

参考文档

MyBatis官方文档

原文地址:https://www.cnblogs.com/bigshark/p/8016757.html