- Mybatis初始化过程 - 通过InputStream来获取配置文件 - ClassLoaderWarpper中的getResourceAsStream可以根据配置的resoutce来获取到配置文件的输入六 - 使用ClassLoader是因为类加载器可具有读取外部资源的能力 - ![image.png](../assets/image_1714227673997_0.png) - 读取到配置文件后传入SqlSessionFactoryBuilder,内部使用XMLConfigBuilder的parse方法读取配置并set到一个configuration变量中返回一个Configuration对象 - ![image.png](../assets/image_1714228148958_0.png) - 使用build方法创建一个DefaultSqlSessionFactory并返回 - 在其中会创建一个SqlSession,其中会创建事务工厂之类的 - ![image.png](../assets/image_1714228719703_0.png) - 将mapper类传入session,通过session.getMapper方法在mapperRegistry获取到一个该mapper类的代理类MapperProxy - 执行时会执行该代理类的invoke方法 - ![image.png](../assets/image_1714230626595_0.png) - 触发mapperMethod的execute方法 - ```java public Object execute(SqlSession sqlSession, Object[] args) { Object result; switch (command.getType()) { case *INSERT*: { Object param = method.convertArgsToSqlCommandParam(args); result = rowCountResult(sqlSession.insert(command.getName(), param)); break; } case *UPDATE*: { Object param = method.convertArgsToSqlCommandParam(args); result = rowCountResult(sqlSession.update(command.getName(), param)); break; } case *DELETE*: { Object param = method.convertArgsToSqlCommandParam(args); result = rowCountResult(sqlSession.delete(command.getName(), param)); break; } case *SELECT*: if (method.returnsVoid() && method.hasResultHandler()) { executeWithResultHandler(sqlSession, args); result = null; } else if (method.returnsMany()) { result = executeForMany(sqlSession, args); } else if (method.returnsMap()) { result = executeForMap(sqlSession, args); } else if (method.returnsCursor()) { result = executeForCursor(sqlSession, args); } else { Object param = method.convertArgsToSqlCommandParam(args); result = sqlSession.selectOne(command.getName(), param); if (method.returnsOptional() && (result == null || !method.getReturnType().equals(result.getClass()))) { result = Optional.*ofNullable*(result); } } break; case *FLUSH*: result = sqlSession.flushStatements(); break; default: throw new BindingException("Unknown execution method for: " + command.getName()); } if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) { throw new BindingException("Mapper method '" + command.getName() + " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ")."); } return result; } ``` - 会根据不同的语句类型执行不同的execute方法,查询list会执行executeForMany方法 - ```java private Object executeForMany(SqlSession sqlSession, Object[] args) { List result; Object param = method.convertArgsToSqlCommandParam(args); if (method.hasRowBounds()) { RowBounds rowBounds = method.extractRowBounds(args); result = sqlSession.selectList(command.getName(), param, rowBounds); } else { result = sqlSession.selectList(command.getName(), param); } *// issue #510 Collections & arrays support * if (!method.getReturnType().isAssignableFrom(result.getClass())) { if (method.getReturnType().isArray()) { return convertToArray(result); } else { return convertToDeclaredCollection(sqlSession.getConfiguration(), result); } } return result; } ``` - selectList获取MappedStatement,再执行executor.query方法 - ```java @Override public List query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException { BoundSql boundSql = ms.getBoundSql(parameterObject); CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql); return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql); } ``` - BoundSql为去掉if,where标签的sql语句,Cachekey为缓存key - 查询时先从缓存获取,获取不到或list为null就执行delegate.query方法查询 - 检查executor是否被关闭,是否清理缓存 - 通过queryFromDatabase,先在缓存中放一个占位符,接着使用doQuery方法查询,然后把缓存中的占位符换成真正的结果 - ```java private List queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException { List list; 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; } ``` - 执行doQuery方法,为BatchExecutor类的方法 - ```java public List doQuery(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException { Statement stmt = null; try { flushStatements(); Configuration configuration = ms.getConfiguration(); StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameterObject, rowBounds, resultHandler, boundSql); Connection connection = getConnection(ms.getStatementLog()); stmt = handler.prepare(connection, transaction.getTimeout()); handler.parameterize(stmt); return handler.query(stmt, resultHandler); } finally { closeStatement(stmt); } } ``` - 通过Statement执行静态语句获取结果 - 执行的是PrepareStatementHandler.query方法,获取结果后交给ResultSetHandler处理,通过resultMap将值赋值给对象