一、简单介绍下 SqlSession
- SqlSession 是⼀个接口,它有两个实现类:DefaultSqlSession(默认)和
SqlSessionManager(弃用,不做介绍) - SqlSession 是 MyBatis 中用于和数据库交互的顶层类,通常将它与 ThreadLocal 绑定,⼀个会话使用⼀个 SqlSession,并且在使用完毕后需要 close
- SqlSession 中的两个最重要的参数,configuration 与初始化时的相同,Executor 为执行器
public class DefaultSqlSession implements SqlSession { private final Configuration configuration; private final Executor executor; }
-
Executor
Executor 也是⼀个接口,他有三个常用的实现类:- BatchExecutor(重用语句并执行批量更新)
- ReuseExecutor(重用预处理语句 prepared statements)
- SimpleExecutor(普通的执行器,默认)
二、生产 DefaultSqlSession 实例对象,设置了事务不自动提交,完成了 executor 对象的创建
- 入口
// 生产了DefaultSqlsession实例对象 设置了事务不自动提交 完成了 executor 对象的创建 SqlSession sqlSession = sqlSessionFactory.openSession();
-
openSession()
中传递三个参数,第一个为默认的执行器 SimpleExecutor,第二个表示事务隔离级别,最后一个参数表示是否自动提交事务,所以一会生产出来的 SqlSession,它需要手动提交事务@Override public SqlSession openSession() { //getDefaultExecutorType()传递的是SimpleExecutor // 第二个参数表示 当前数据库事务的隔离级别 // 最后一个参数表示是否自动提交事务 return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false); } public ExecutorType getDefaultExecutorType() { return defaultExecutorType; } protected ExecutorType defaultExecutorType = ExecutorType.SIMPLE;
-
openSessionFromDataSource()
方法//进入openSessionFromDataSource。 //ExecutorType 为Executor的类型,TransactionIsolationLevel为事务隔离级别,autoCommit是否开启事务 //openSession的多个重载方法可以指定获得的SeqSession的Executor类型和事务的处理 private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) { Transaction tx = null; try { // 获得 Environment 对象 final Environment environment = configuration.getEnvironment(); // 创建 Transaction 对象 final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment); tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit); // 创建 Executor 对象 final Executor executor = configuration.newExecutor(tx, execType); // 创建 DefaultSqlSession 对象 return new DefaultSqlSession(configuration, executor, autoCommit); } catch (Exception e) { // 如果发生异常,则关闭 Transaction 对象 closeTransaction(tx); // may have fetched a connection so lets call close() throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e); } finally { ErrorContext.instance().reset(); } }
- 开始使用 SqlSession,根据 statementId 来从 configuration 中的 map 集合中获取到了指定的 MappedStatement 对象,并将查询任务委派给了 executor 执行器
//进入selectList方法,多个重载方法 @Override public <E> List<E> selectList(String statement) { return this.selectList(statement, null); } @Override public <E> List<E> selectList(String statement, Object parameter) { return this.selectList(statement, parameter, RowBounds.DEFAULT); } @Override public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) { try { // 获得 MappedStatement 对象 MappedStatement ms = configuration.getMappedStatement(statement); // 执行查询 return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER); } catch (Exception e) { throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e); } finally { ErrorContext.instance().reset(); } }
三、Executor
- 先点进
executor.query()
方法,发现真正的实现类是 BaseExecutor,他是 SimpleExecutor 的父类//此方法在SimpleExecutor的父类BaseExecutor中实现 @Override public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException { //根据传入的参数动态获得SQL语句,最后返回用BoundSql对象表示 BoundSql boundSql = ms.getBoundSql(parameter); //为本次查询创建缓存的Key CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql); // 查询 return query(ms, parameter, rowBounds, resultHandler, key, boundSql); }
- 继续点击
@Override public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException { ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId()); // 已经关闭,则抛出 ExecutorException 异常 if (closed) { throw new ExecutorException("Executor was closed."); } // 清空本地缓存,如果 queryStack 为零,并且要求清空本地缓存。 if (queryStack == 0 && ms.isFlushCacheRequired()) { clearLocalCache(); } List<E> list; try { // queryStack + 1 queryStack++; // 从一级缓存中,获取查询结果 list = resultHandler == null ? (List<E>) localCache.getObject(key) : null; // 获取到,则进行处理 if (list != null) { handleLocallyCachedOutputParameters(ms, key, parameter, boundSql); // 获得不到,则从数据库中查询 } else { list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql); } } finally { // queryStack - 1 queryStack--; } if (queryStack == 0) { // 执行延迟加载 for (DeferredLoad deferredLoad : deferredLoads) { deferredLoad.load(); } // issue #601 // 清空 deferredLoads deferredLoads.clear(); // 如果缓存级别是 LocalCacheScope.STATEMENT ,则进行清理 if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) { // issue #482 clearLocalCache(); } } return list; }
- 查询数据库的方法
// 从数据库中读取操作 private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException { List<E> list; // 在缓存中,添加占位对象。此处的占位符,和延迟加载有关,可见 `DeferredLoad#canLoad()` 方法 localCache.putObject(key, EXECUTION_PLACEHOLDER); try { // 执行读操作 list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql); } finally { // 从缓存中,移除占位对象 localCache.removeObject(key); } // 添加到缓存中 localCache.putObject(key, list); // 暂时忽略,存储过程相关 if (ms.getStatementType() == StatementType.CALLABLE) { localOutputParameterCache.putObject(key, parameter); } return list; }
- 将 JDBC 查询代码再次委派给 StatementHandler 去执行
@Override public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException { Statement stmt = null; try { Configuration configuration = ms.getConfiguration(); // 传入参数创建StatementHanlder对象来执行查询 StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql); // 创建jdbc中的statement对象 stmt = prepareStatement(handler, ms.getStatementLog()); // 执行 StatementHandler ,进行读操作 return handler.query(stmt, resultHandler); } finally { // 关闭 StatementHandler 对象 closeStatement(stmt); } } // 初始化 StatementHandler 对象 private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException { Statement stmt; // 获得 Connection 对象 Connection connection = getConnection(statementLog); // 创建 Statement 或 PrepareStatement 对象 stmt = handler.prepare(connection, transaction.getTimeout()); // 设置 SQL 上的参数,例如 PrepareStatement 对象上的占位符 handler.parameterize(stmt); return stmt; }
四、StatementHandler
- StatementHandler 对象主要完成两个工作
- 对于 JDBC 的 PreparedStatement 类型的对象,创建的过程中,我们使用的是SQL语句字符串会包含若干个 "?" 占位符,我们其后再对占位符进行设值。StatementHandler 通过
parameterize(statement)
方法对 S tatement 进行设值 - StatementHandler 通过
List query(Statement statement, ResultHandler resultHandler)
方法来完成执行 Statement,和将 Statement 对象返回的 resultSet 封装成 List
- 对于 JDBC 的 PreparedStatement 类型的对象,创建的过程中,我们使用的是SQL语句字符串会包含若干个 "?" 占位符,我们其后再对占位符进行设值。StatementHandler 通过
- 进入
handler.parameterize(stmt);
@Override public void parameterize(Statement statement) throws SQLException { //使用ParameterHandler对象来完成对Statement的设值 parameterHandler.setParameters((PreparedStatement) statement); } @Override public void setParameters(PreparedStatement ps) { ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId()); // 遍历 ParameterMapping 数组 List<ParameterMapping> parameterMappings = boundSql.getParameterMappings(); if (parameterMappings != null) { for (int i = 0; i < parameterMappings.size(); i++) { // 获得 ParameterMapping 对象 ParameterMapping parameterMapping = parameterMappings.get(i); if (parameterMapping.getMode() != ParameterMode.OUT) { // 获得值 Object value; String propertyName = parameterMapping.getProperty(); if (boundSql.hasAdditionalParameter(propertyName)) { // issue #448 ask first for additional params value = boundSql.getAdditionalParameter(propertyName); } else if (parameterObject == null) { value = null; } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) { value = parameterObject; } else { MetaObject metaObject = configuration.newMetaObject(parameterObject); value = metaObject.getValue(propertyName); } // 获得 typeHandler、jdbcType 属性 TypeHandler typeHandler = parameterMapping.getTypeHandler(); JdbcType jdbcType = parameterMapping.getJdbcType(); if (value == null && jdbcType == null) { jdbcType = configuration.getJdbcTypeForNull(); } // 设置 ? 占位符的参数 try { typeHandler.setParameter(ps, i + 1, value, jdbcType); } catch (TypeException | SQLException e) { throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e); } } } } }
- 回到 SimpleExecutor 的
doQuery()
方法中,继续进入handler.query(stmt, resultHandler);
@Override public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException { Statement stmt = null; try { Configuration configuration = ms.getConfiguration(); // 传入参数创建StatementHanlder对象来执行查询 StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql); // 创建jdbc中的statement对象 stmt = prepareStatement(handler, ms.getStatementLog()); // 执行 StatementHandler ,进行读操作 return handler.query(stmt, resultHandler); } finally { // 关闭 StatementHandler 对象 closeStatement(stmt); } } @Override public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException { PreparedStatement ps = (PreparedStatement) statement; // 执行查询 ps.execute(); // 处理返回结果 return resultSetHandler.handleResultSets(ps); }
- 处理返回结果集
@Override public List<Object> handleResultSets(Statement stmt) throws SQLException { ErrorContext.instance().activity("handling results").object(mappedStatement.getId()); // 多 ResultSet 的结果集合,每个 ResultSet 对应一个 Object 对象。而实际上,每个 Object 是 List<Object> 对象。 // 在不考虑存储过程的多 ResultSet 的情况,普通的查询,实际就一个 ResultSet ,也就是说,multipleResults 最多就一个元素。 final List<Object> multipleResults = new ArrayList<>(); int resultSetCount = 0; // 获得首个 ResultSet 对象,并封装成 ResultSetWrapper 对象 ResultSetWrapper rsw = getFirstResultSet(stmt); // 获得 ResultMap 数组 // 在不考虑存储过程的多 ResultSet 的情况,普通的查询,实际就一个 ResultSet ,也就是说,resultMaps 就一个元素。 List<ResultMap> resultMaps = mappedStatement.getResultMaps(); int resultMapCount = resultMaps.size(); validateResultMapsCount(rsw, resultMapCount); // 校验 while (rsw != null && resultMapCount > resultSetCount) { // 获得 ResultMap 对象 ResultMap resultMap = resultMaps.get(resultSetCount); // 处理 ResultSet ,将结果添加到 multipleResults 中 handleResultSet(rsw, resultMap, multipleResults, null); // 获得下一个 ResultSet 对象,并封装成 ResultSetWrapper 对象 rsw = getNextResultSet(stmt); // 清理 cleanUpAfterHandlingResultSet(); // resultSetCount ++ resultSetCount++; } // 因为 `mappedStatement.resultSets` 只在存储过程中使用,本系列暂时不考虑,忽略即可 String[] resultSets = mappedStatement.getResultSets(); if (resultSets != null) { while (rsw != null && resultSetCount < resultSets.length) { ResultMapping parentMapping = nextResultMaps.get(resultSets[resultSetCount]); if (parentMapping != null) { String nestedResultMapId = parentMapping.getNestedResultMapId(); ResultMap resultMap = configuration.getResultMap(nestedResultMapId); handleResultSet(rsw, resultMap, null, parentMapping); } rsw = getNextResultSet(stmt); cleanUpAfterHandlingResultSet(); resultSetCount++; } } // 如果是 multipleResults 单元素,则取首元素返回 return collapseSingleResultList(multipleResults); }
// 处理 ResultSet ,将结果添加到 multipleResults 中 private void handleResultSet(ResultSetWrapper rsw, ResultMap resultMap, List<Object> multipleResults, ResultMapping parentMapping) throws SQLException { try { // 暂时忽略,因为只有存储过程的情况,调用该方法,parentMapping 为非空 if (parentMapping != null) { handleRowValues(rsw, resultMap, null, RowBounds.DEFAULT, parentMapping); } else { // 如果没有自定义的 resultHandler ,则创建默认的 DefaultResultHandler 对象 if (resultHandler == null) { // 创建 DefaultResultHandler 对象 DefaultResultHandler defaultResultHandler = new DefaultResultHandler(objectFactory); // 处理 ResultSet 返回的每一行 Row handleRowValues(rsw, resultMap, defaultResultHandler, rowBounds, null); // 添加 defaultResultHandler 的处理的结果,到 multipleResults 中 multipleResults.add(defaultResultHandler.getResultList()); } else { // 处理 ResultSet 返回的每一行 Row handleRowValues(rsw, resultMap, resultHandler, rowBounds, null); } } } finally { // issue #228 (close resultsets) // 关闭 ResultSet 对象 closeResultSet(rsw.getResultSet()); } }
// 处理 ResultSet 返回的每一行 Row public void handleRowValues(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException { // 处理嵌套映射的情况 if (resultMap.hasNestedResultMaps()) { // 校验不要使用 RowBounds ensureNoRowBounds(); // 校验不要使用自定义的 resultHandler checkResultHandler(); // 处理嵌套映射的结果 handleRowValuesForNestedResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping); // 处理简单映射的情况 } else { // 处理简单映射的结果 handleRowValuesForSimpleResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping); } }