# mybatis-3 **Repository Path**: csuliunian/mybatis-3 ## Basic Information - **Project Name**: mybatis-3 - **Description**: mybatis源码 - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-10-15 - **Last Updated**: 2024-06-29 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## 基础 * [文档](http://mybatis.github.io/mybatis-3) * [最新稳定版](https://github.com/mybatis/mybatis-3/releases) * [快照版](https://oss.sonatype.org/content/repositories/snapshots/org/mybatis/mybatis/) ## 源码 ### 如何获取数据源 datasource 通过BaseBuilder的实现类XMLConfigBuilder 解析配置文件,parse方法会返回解析完的Configuration类,解析过程中会获取到environments标签下的datasource的标签配置信息 ```text String id = child.getStringAttribute("id"); if (isSpecifiedEnvironment(id)) { // 1. 事务管理工厂 TransactionFactory txFactory = transactionManagerElement(child.evalNode("transactionManager")); // 2. 解析配置的数据源 DataSourceFactory dsFactory = dataSourceElement(child.evalNode("dataSource")); // 3. 将解析获取到的数据源,事务管理工厂放到全局configuration中 DataSource dataSource = dsFactory.getDataSource(); Environment.Builder environmentBuilder = new Environment.Builder(id) .transactionFactory(txFactory) .dataSource(dataSource); configuration.setEnvironment(environmentBuilder.build()); } ``` ### 如何获取sql 1. XMLMapperBuilder解析mapper的xml文件,获取到具体的insert delete update select,然后通过XMLStatementBuilder来解析,解析出的sql放入MapperBuilderAssistant ```text private void configurationElement(XNode context) { try { String namespace = context.getStringAttribute("namespace"); if (namespace == null || namespace.isEmpty()) { throw new BuilderException("Mapper's namespace cannot be empty"); } builderAssistant.setCurrentNamespace(namespace); cacheRefElement(context.evalNode("cache-ref")); cacheElement(context.evalNode("cache")); parameterMapElement(context.evalNodes("/mapper/parameterMap")); // resultMap resultMapElements(context.evalNodes("/mapper/resultMap")); // sql语句,公共的语句 sqlElement(context.evalNodes("/mapper/sql")); // 实际的sql语句,分以下四种类型 buildStatementFromContext(context.evalNodes("select|insert|update|delete")); } catch (Exception e) { throw new BuilderException("Error parsing Mapper XML. The XML location is '" + resource + "'. Cause: " + e, e); } } ``` ```text private void buildStatementFromContext(List list, String requiredDatabaseId) { for (XNode context : list) { final XMLStatementBuilder statementParser = new XMLStatementBuilder(configuration, builderAssistant, context, requiredDatabaseId); try { statementParser.parseStatementNode(); } catch (IncompleteElementException e) { configuration.addIncompleteStatement(statementParser); } } } ``` 2. MapperAnnotationBuilder 解析@Mapper注解的类,该类上可以通过@Select注解编写sql语句 ### 如何执行具体操作 #### 执行器类型 - SIMPLE - REUSE - BATCH #### select 1. sqlSession.getOne/getList最终都会调用到getList 2. getList中用执行器Executor调用query方法 3. BaseExecutor.query 方法 调用子类实现的doQuery方法 4. doQuery方法中调用prepareStatement生成Statement 5. 然后交由StatementHandler去具体执行 ```text private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException { Statement stmt; Connection connection = getConnection(statementLog); stmt = handler.prepare(connection, transaction.getTimeout()); handler.parameterize(stmt); return stmt; } ``` #### update insert delete