zoukankan      html  css  js  c++  java
  • 课时 20:MyBatis架构和SqlSessionFactory源码分析

    .1)分析mybatis的架构(四层架构)

      1.接口层(广义接口)

        1.1 增加接口方法 删除 增加 修改 查询 各种直接使用的配置方法

      2.数据处理层

        2.1 列如select * from student where name=#{} and age=#{}

          2.1.1 首先处理参数

          2.1.2 处理完参数 之后解析SQL

          2.1.3 解析完SQL之后数据库就知道你要干嘛了 开始执行SQL(Executor)

          2.1.4 执行完SQL 开始处理结果

      3.框架支撑层

         3.1 事务管理 缓存机制 连接池管理等等(各种辅助功能)

      4.引导层
         4.1 SQL语句的方式:XML配置 or 注解方式

    .2)获取SqlSessionFactory源码分析  

      1.获取了一个parse解析器

    XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);

      2.通过configuration标签 设置了很多个子参数 properties丶settings丶typeAliases等等子标签

     this.parseConfiguration(this.parser.evalNode("/configuration"));

        2.1 上面调用的方法如下

    private void parseConfiguration(XNode root) {
            try {
                this.propertiesElement(root.evalNode("properties"));
                Properties settings = this.settingsAsProperties(root.evalNode("settings"));
                this.loadCustomVfs(settings);
                this.typeAliasesElement(root.evalNode("typeAliases"));
                this.pluginElement(root.evalNode("plugins"));
                this.objectFactoryElement(root.evalNode("objectFactory"));
                this.objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
                this.reflectorFactoryElement(root.evalNode("reflectorFactory"));
                this.settingsElement(settings);
                this.environmentsElement(root.evalNode("environments"));
                this.databaseIdProviderElement(root.evalNode("databaseIdProvider"));
                this.typeHandlerElement(root.evalNode("typeHandlers"));
                this.mapperElement(root.evalNode("mappers"));
            } catch (Exception var3) {
                throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + var3, var3);
            }
        }

        2.2 分析几个代表性的标签

          2.2.1 settings分析

            2.2.1.1 设置标签中通过settingsElment()方法 创建了很多子元素 并且带有默认值

    private void settingsElement(Properties props) throws Exception {
            this.configuration.setAutoMappingBehavior(AutoMappingBehavior.valueOf(props.getProperty("autoMappingBehavior", "PARTIAL")));
            this.configuration.setAutoMappingUnknownColumnBehavior(AutoMappingUnknownColumnBehavior.valueOf(props.getProperty("autoMappingUnknownColumnBehavior", "NONE")));
            this.configuration.setCacheEnabled(this.booleanValueOf(props.getProperty("cacheEnabled"), true));
            this.configuration.setProxyFactory((ProxyFactory)this.createInstance(props.getProperty("proxyFactory")));
            this.configuration.setLazyLoadingEnabled(this.booleanValueOf(props.getProperty("lazyLoadingEnabled"), false));
            this.configuration.setAggressiveLazyLoading(this.booleanValueOf(props.getProperty("aggressiveLazyLoading"), false));
            this.configuration.setMultipleResultSetsEnabled(this.booleanValueOf(props.getProperty("multipleResultSetsEnabled"), true));
            this.configuration.setUseColumnLabel(this.booleanValueOf(props.getProperty("useColumnLabel"), true));
            this.configuration.setUseGeneratedKeys(this.booleanValueOf(props.getProperty("useGeneratedKeys"), false));
            this.configuration.setDefaultExecutorType(ExecutorType.valueOf(props.getProperty("defaultExecutorType", "SIMPLE")));
            this.configuration.setDefaultStatementTimeout(this.integerValueOf(props.getProperty("defaultStatementTimeout"), (Integer)null));
            this.configuration.setDefaultFetchSize(this.integerValueOf(props.getProperty("defaultFetchSize"), (Integer)null));
            this.configuration.setMapUnderscoreToCamelCase(this.booleanValueOf(props.getProperty("mapUnderscoreToCamelCase"), false));
            this.configuration.setSafeRowBoundsEnabled(this.booleanValueOf(props.getProperty("safeRowBoundsEnabled"), false));
            this.configuration.setLocalCacheScope(LocalCacheScope.valueOf(props.getProperty("localCacheScope", "SESSION")));
            this.configuration.setJdbcTypeForNull(JdbcType.valueOf(props.getProperty("jdbcTypeForNull", "OTHER")));
            this.configuration.setLazyLoadTriggerMethods(this.stringSetValueOf(props.getProperty("lazyLoadTriggerMethods"), "equals,clone,hashCode,toString"));
            this.configuration.setSafeResultHandlerEnabled(this.booleanValueOf(props.getProperty("safeResultHandlerEnabled"), true));
            this.configuration.setDefaultScriptingLanguage(this.resolveClass(props.getProperty("defaultScriptingLanguage")));
            Class<? extends TypeHandler> typeHandler = this.resolveClass(props.getProperty("defaultEnumTypeHandler"));
            this.configuration.setDefaultEnumTypeHandler(typeHandler);
            this.configuration.setCallSettersOnNulls(this.booleanValueOf(props.getProperty("callSettersOnNulls"), false));
            this.configuration.setUseActualParamName(this.booleanValueOf(props.getProperty("useActualParamName"), true));
            this.configuration.setReturnInstanceForEmptyRow(this.booleanValueOf(props.getProperty("returnInstanceForEmptyRow"), false));
            this.configuration.setLogPrefix(props.getProperty("logPrefix"));
            Class<? extends Log> logImpl = this.resolveClass(props.getProperty("logImpl"));
            this.configuration.setLogImpl(logImpl);
            this.configuration.setConfigurationFactory(this.resolveClass(props.getProperty("configurationFactory")));
        }

          2.2.2 分析mappers分析

            2.2.2.1 通过这个来分析不同的映射SQL映射文件

    private void mapperElement(XNode parent) throws Exception {
            if (parent != null) {
                Iterator var2 = parent.getChildren().iterator();
    
                while(true) {
                    while(var2.hasNext()) {
                        XNode child = (XNode)var2.next();
                        String resource;
                        if ("package".equals(child.getName())) {
                            resource = child.getStringAttribute("name");
                            this.configuration.addMappers(resource);
                        } else {
                            resource = child.getStringAttribute("resource");
                            String url = child.getStringAttribute("url");
                            String mapperClass = child.getStringAttribute("class");
                            XMLMapperBuilder mapperParser;
                            InputStream inputStream;
                            if (resource != null && url == null && mapperClass == null) {
                                ErrorContext.instance().resource(resource);
                                inputStream = Resources.getResourceAsStream(resource);
                                mapperParser = new XMLMapperBuilder(inputStream, this.configuration, resource, this.configuration.getSqlFragments());
                                mapperParser.parse();
                            } else if (resource == null && url != null && mapperClass == null) {
                                ErrorContext.instance().resource(url);
                                inputStream = Resources.getUrlAsStream(url);
                                mapperParser = new XMLMapperBuilder(inputStream, this.configuration, url, this.configuration.getSqlFragments());
                                mapperParser.parse();
                            } else {
                                if (resource != null || url != null || mapperClass == null) {
                                    throw new BuilderException("A mapper element may only specify a url, resource or class, but not more than one.");
                                }
    
                                Class<?> mapperInterface = Resources.classForName(mapperClass);
                                this.configuration.addMapper(mapperInterface);
                            }
                        }
                    }
    
                    return;
                }
            }
        }
    mapperParser.parse();

            2.2.2.2 通过进一步的发现 开始解析SQL文件的增删改查操作

    this.configurationElement(this.parser.evalNode("/mapper"));

            2.2.2.3 通过上面的方法开始解析SQL映射文件

     this.buildStatementFromContext(context.evalNodes("select|insert|update|delete"));

            2.2.2.4 parseStatementNode()方法来解析标签属性

    public void parseStatementNode() {
            String id = this.context.getStringAttribute("id");
            String databaseId = this.context.getStringAttribute("databaseId");
            if (this.databaseIdMatchesCurrent(id, databaseId, this.requiredDatabaseId)) {
                Integer fetchSize = this.context.getIntAttribute("fetchSize");
                Integer timeout = this.context.getIntAttribute("timeout");
                String parameterMap = this.context.getStringAttribute("parameterMap");
                String parameterType = this.context.getStringAttribute("parameterType");
                Class<?> parameterTypeClass = this.resolveClass(parameterType);
                String resultMap = this.context.getString
    Attribute("resultMap"); String resultType = this.context.getStringAttribute("resultType"); String lang = this.context.getStringAttribute("lang"); LanguageDriver langDriver = this.getLanguageDriver(lang); Class<?> resultTypeClass = this.resolveClass(resultType); String resultSetType = this.context.getStringAttribute("resultSetType"); StatementType statementType = StatementType.valueOf(this.context.getStringAttribute("statementType", StatementType.PREPARED.toString())); ResultSetType resultSetTypeEnum = this.resolveResultSetType(resultSetType); String nodeName = this.context.getNode().getNodeName(); SqlCommandType sqlCommandType = SqlCommandType.valueOf(nodeName.toUpperCase(Locale.ENGLISH)); boolean isSelect = sqlCommandType == SqlCommandType.SELECT; boolean flushCache = this.context.getBooleanAttribute("flushCache", !isSelect); boolean useCache = this.context.getBooleanAttribute("useCache", isSelect); boolean resultOrdered = this.context.getBooleanAttribute("resultOrdered", false); XMLIncludeTransformer includeParser = new XMLIncludeTransformer(this.configuration, this.builderAssistant); includeParser.applyIncludes(this.context.getNode()); this.processSelectKeyNodes(id, parameterTypeClass, langDriver); SqlSource sqlSource = langDriver.createSqlSource(this.configuration, this.context, parameterTypeClass); String resultSets = this.context.getStringAttribute("resultSets"); String keyProperty = this.context.getStringAttribute("keyProperty"); String keyColumn = this.context.getStringAttribute("keyColumn"); String keyStatementId = id + "!selectKey"; keyStatementId = this.builderAssistant.applyCurrentNamespace(keyStatementId, true); Object keyGenerator; if (this.configuration.hasKeyGenerator(keyStatementId)) { keyGenerator = this.configuration.getKeyGenerator(keyStatementId); } else { keyGenerator = this.context.getBooleanAttribute("useGeneratedKeys", this.configuration.isUseGeneratedKeys() && SqlCommandType.INSERT.equals(sqlCommandType)) ? Jdbc3KeyGenerator.INSTANCE : NoKeyGenerator.INSTANCE; } //这个方法用于构建出一个statement对象 this.builderAssistant.addMappedStatement(id, sqlSource, statementType, sqlCommandType, fetchSize, timeout, parameterMap, parameterTypeClass, resultMap, resultTypeClass, resultSetTypeEnum, flushCache, useCache, resultOrdered, (KeyGenerator)keyGenerator, keyProperty, keyColumn, databaseId, langDriver, resultSets); } }

            2.2.2.5 在解析完成会将select等标签封装成一个MappedStatement类

               即 MappedStatement就是select 标签

     public MappedStatement addMappedStatement(String id, SqlSource sqlSource, StatementType statementType, SqlCommandType sqlCommandType, Integer fetchSize, Integer timeout, String parameterMap, Class<?> parameterType, String resultMap, Class<?> resultType, ResultSetType resultSetType, boolean flushCache, boolean useCache, boolean resultOrdered, KeyGenerator keyGenerator, String keyProperty, String keyColumn, String databaseId, LanguageDriver lang, String resultSets) {
            if (this.unresolvedCacheRef) {
                throw new IncompleteElementException("Cache-ref not yet resolved");
            } else {
                id = this.applyCurrentNamespace(id, false);
                boolean isSelect = sqlCommandType == SqlCommandType.SELECT;
                org.apache.ibatis.mapping.MappedStatement.Builder statementBuilder = (new org.apache.ibatis.mapping.MappedStatement.Builder(this.configuration, id, sqlSource, sqlCommandType)).resource(this.resource).fetchSize(fetchSize).timeout(timeout).statementType(statementType).keyGenerator(keyGenerator).keyProperty(keyProperty).keyColumn(keyColumn).databaseId(databaseId).lang(lang).resultOrdered(resultOrdered).resultSets(resultSets).resultMaps(this.getStatementResultMaps(resultMap, resultType, id)).resultSetType(resultSetType).flushCacheRequired((Boolean)this.valueOrDefault(flushCache, !isSelect)).useCache((Boolean)this.valueOrDefault(useCache, isSelect)).cache(this.currentCache);
                ParameterMap statementParameterMap = this.getStatementParameterMap(parameterMap, parameterType, id);
                if (statementParameterMap != null) {
                    statementBuilder.parameterMap(statementParameterMap);
                }
    
                MappedStatement statement = statementBuilder.build();
                this.configuration.addMappedStatement(statement);
                return statement;
            }
        }

       3.MappedStatement --->存在于Configuration中 environment--->存在于Configuration中

        所有的配置信息都存在于Configuration中

        Configuration有存在于DefaultSqlSessionFactory对象中(SqlSessionFactory)-->SqlSessionFactory 多态的体现

      4.结构

         4.1 SqlSessionFactory --> DefaultSqlSessionFactory-->Configuration-->包含了一切信息 

  • 相关阅读:
    多线程 thread和Task的用法以及注意事项
    Application.DoEvents()的使用
    测试
    python-包管理工具-pip
    压缩下载文件
    如何修改Django中的日期和时间格式 DateTimeField
    Django model数据 时间格式
    模板语法
    Django框架基础-MTV模型
    view架构
  • 原文地址:https://www.cnblogs.com/thisHBZ/p/12461888.html
Copyright © 2011-2022 走看看