每个基于 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 publicList 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 Listlist; 6 try { 7 queryStack++; 8 list = resultHandler == null ? (List ) 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 privateList queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException { 2 List 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 // 把查询结果放入缓存后返回结果list10 localCache.putObject(key, list);11 if (ms.getStatementType() == StatementType.CALLABLE) {12 localOutputParameterCache.putObject(key, parameter);13 }14 return list;15 }
1 @Override 2 publicList 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. query(stmt, resultHandler);11 } finally {12 closeStatement(stmt);13 }14 }
1 @Override2 publicList query(Statement statement, ResultHandler resultHandler) throws SQLException {3 String sql = boundSql.getSql();4 statement.execute(sql);5 return resultSetHandler. handleResultSets(statement);6 }
参考文档