最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Mybatis?sql與xml文件讀取方法詳細(xì)分析

 更新時間:2023年01月28日 10:50:45   作者:xl649138628  
這篇文章主要介紹了Mybatis?sql與xml文件讀取方法,在執(zhí)行一個自定義sql語句時,dao對應(yīng)的代理對象時如何找到sql,也就是dao的代理對象和sql之間的關(guān)聯(lián)關(guān)系是如何建立的

在執(zhí)行一個自定義sql語句時,dao對應(yīng)的代理對象時如何找到sql,也就是dao的代理對象和sql之間的關(guān)聯(lián)關(guān)系是如何建立的。

        在mybatis中的MybatisPlusAutoConfiguration類被@Configuration注解,在該類中通過被@Bean注解的sqlSessionFactory方法向spring上下文注入bean并生成SqlSessionFactory類型的bean實例。關(guān)注該方法的最后一行代碼。

    @Bean
    @ConditionalOnMissingBean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
        // TODO 使用 MybatisSqlSessionFactoryBean 而不是 SqlSessionFactoryBean
        MybatisSqlSessionFactoryBean factory = new MybatisSqlSessionFactoryBean();
        factory.setDataSource(dataSource);
        factory.setVfs(SpringBootVFS.class);
        if (StringUtils.hasText(this.properties.getConfigLocation())) {
            factory.setConfigLocation(this.resourceLoader.getResource(this.properties.getConfigLocation()));
        }
        applyConfiguration(factory);
        if (this.properties.getConfigurationProperties() != null) {
            factory.setConfigurationProperties(this.properties.getConfigurationProperties());
        }
        if (!ObjectUtils.isEmpty(this.interceptors)) {
            factory.setPlugins(this.interceptors);
        }
        if (this.databaseIdProvider != null) {
            factory.setDatabaseIdProvider(this.databaseIdProvider);
        }
        if (StringUtils.hasLength(this.properties.getTypeAliasesPackage())) {
            factory.setTypeAliasesPackage(this.properties.getTypeAliasesPackage());
        }
        if (this.properties.getTypeAliasesSuperType() != null) {
            factory.setTypeAliasesSuperType(this.properties.getTypeAliasesSuperType());
        }
        if (StringUtils.hasLength(this.properties.getTypeHandlersPackage())) {
            factory.setTypeHandlersPackage(this.properties.getTypeHandlersPackage());
        }
        if (!ObjectUtils.isEmpty(this.typeHandlers)) {
            factory.setTypeHandlers(this.typeHandlers);
        }
        Resource[] mapperLocations = this.properties.resolveMapperLocations();
        if (!ObjectUtils.isEmpty(mapperLocations)) {
            factory.setMapperLocations(mapperLocations);
        }
        // TODO 修改源碼支持定義 TransactionFactory
        this.getBeanThen(TransactionFactory.class, factory::setTransactionFactory);
        // TODO 對源碼做了一定的修改(因為源碼適配了老舊的mybatis版本,但我們不需要適配)
        Class<? extends LanguageDriver> defaultLanguageDriver = this.properties.getDefaultScriptingLanguageDriver();
        if (!ObjectUtils.isEmpty(this.languageDrivers)) {
            factory.setScriptingLanguageDrivers(this.languageDrivers);
        }
        Optional.ofNullable(defaultLanguageDriver).ifPresent(factory::setDefaultScriptingLanguageDriver);
        // TODO 自定義枚舉包
        if (StringUtils.hasLength(this.properties.getTypeEnumsPackage())) {
            factory.setTypeEnumsPackage(this.properties.getTypeEnumsPackage());
        }
        // TODO 此處必為非 NULL
        GlobalConfig globalConfig = this.properties.getGlobalConfig();
        // TODO 注入填充器
        this.getBeanThen(MetaObjectHandler.class, globalConfig::setMetaObjectHandler);
        // TODO 注入主鍵生成器
        this.getBeanThen(IKeyGenerator.class, i -> globalConfig.getDbConfig().setKeyGenerator(i));
        // TODO 注入sql注入器
        this.getBeanThen(ISqlInjector.class, globalConfig::setSqlInjector);
        // TODO 注入ID生成器
        this.getBeanThen(IdentifierGenerator.class, globalConfig::setIdentifierGenerator);
        // TODO 設(shè)置 GlobalConfig 到 MybatisSqlSessionFactoryBean
        factory.setGlobalConfig(globalConfig);
        //關(guān)注該行代碼
        return factory.getObject();
    }

        進入最后一行代碼找到MybatisSqlSessionFactoryBean類里的getObject方法,然后進入到該類的afterPropertiesSet方法,找到了buildSqlSessionFactory方法。

public SqlSessionFactory getObject() throws Exception {
        if (this.sqlSessionFactory == null) {
            //關(guān)注該行方法
            afterPropertiesSet();
        }
        return this.sqlSessionFactory;
}
public void afterPropertiesSet() throws Exception {
        notNull(dataSource, "Property 'dataSource' is required");
        state((configuration == null && configLocation == null) || !(configuration != null && configLocation != null),
            "Property 'configuration' and 'configLocation' can not specified with together");
        //關(guān)注該行方法
        this.sqlSessionFactory = buildSqlSessionFactory();
 }

 在buildSqlSessionFactory中有兩處代碼比較關(guān)鍵,第一處如下圖hasLength(this.typeAliasesPackage)判斷了在yml中配置的的mybatis-plus.typeAliasesPackage,并通過buildSqlSessionFactory方法里的scanClasses方法將讀取到的類路徑全部小寫后存放到TypeAliasRegistry類的typeAliases屬性的hashMap緩存中。

mybatis-plus:
  mapper-locations: classpath*:mapper/*.xml
  typeAliasesPackage: >
    com.changshin.entity.po
  global-config:
    id-type: 0  # 0:數(shù)據(jù)庫ID自增   1:用戶輸入id  2:全局唯一id(IdWorker)  3:全局唯一ID(uuid)
    db-column-underline: false
    refresh-mapper: true
  configuration:
    map-underscore-to-camel-case: true
    cache-enabled: true #配置的緩存的全局開關(guān)
    lazyLoadingEnabled: true #延時加載的開關(guān)
    multipleResultSetsEnabled: true #開啟的話,延時加載一個屬性時會加載該對象全部屬性,否則按需加載屬性
 protected SqlSessionFactory buildSqlSessionFactory() throws Exception {
        final Configuration targetConfiguration;
        // TODO 使用 MybatisXmlConfigBuilder 而不是 XMLConfigBuilder
        MybatisXMLConfigBuilder xmlConfigBuilder = null;
        if (this.configuration != null) {
            targetConfiguration = this.configuration;
            if (targetConfiguration.getVariables() == null) {
                targetConfiguration.setVariables(this.configurationProperties);
            } else if (this.configurationProperties != null) {
                targetConfiguration.getVariables().putAll(this.configurationProperties);
            }
        } else if (this.configLocation != null) {
            // TODO 使用 MybatisXMLConfigBuilder
            xmlConfigBuilder = new MybatisXMLConfigBuilder(this.configLocation.getInputStream(), null, this.configurationProperties);
            targetConfiguration = xmlConfigBuilder.getConfiguration();
        } else {
            LOGGER.debug(() -> "Property 'configuration' or 'configLocation' not specified, using default MyBatis Configuration");
            // TODO 使用 MybatisConfiguration
            targetConfiguration = new MybatisConfiguration();
            Optional.ofNullable(this.configurationProperties).ifPresent(targetConfiguration::setVariables);
        }
        //省略。。。。。。。
 
        if (hasLength(this.typeAliasesPackage)) {
            scanClasses(this.typeAliasesPackage, this.typeAliasesSuperType).stream()
                .filter(clazz -> !clazz.isAnonymousClass()).filter(clazz -> !clazz.isInterface())
                .filter(clazz -> !clazz.isMemberClass()).forEach(targetConfiguration.getTypeAliasRegistry()::registerAlias);
        }
        //省略。。。。。。。。。。。。。。。。。。。。。。。。
        if (this.mapperLocations != null) {
            if (this.mapperLocations.length == 0) {
                LOGGER.warn(() -> "Property 'mapperLocations' was specified but matching resources are not found.");
            } else {
                // 關(guān)注for循環(huán)結(jié)構(gòu)體里的代碼
                for (Resource mapperLocation : this.mapperLocations) {
                    if (mapperLocation == null) {
                        continue;
                    }
                    try {
                        XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(mapperLocation.getInputStream(),
                            targetConfiguration, mapperLocation.toString(), targetConfiguration.getSqlFragments());
                        xmlMapperBuilder.parse();
                    } catch (Exception e) {
                        throw new NestedIOException("Failed to parse mapping resource: '" + mapperLocation + "'", e);
                    } finally {
                        ErrorContext.instance().reset();
                    }
                    LOGGER.debug(() -> "Parsed mapper file: '" + mapperLocation + "'");
                }
            }
        } else {
            LOGGER.debug(() -> "Property 'mapperLocations' was not specified.");
        }
        final SqlSessionFactory sqlSessionFactory = new MybatisSqlSessionFactoryBuilder().build(targetConfiguration);
        // TODO SqlRunner
        SqlHelper.FACTORY = sqlSessionFactory;
        // TODO 打印騷東西 Banner
        if (globalConfig.isBanner()) {
            System.out.println(" _ _   |_  _ _|_. ___ _ |    _ ");
            System.out.println("| | |\\/|_)(_| | |_\\  |_)||_|_\\ ");
            System.out.println("     /               |         ");
            System.out.println("                        " + MybatisPlusVersion.getVersion() + " ");
        }
        return sqlSessionFactory;
    }

第二處xmlMapperBuilder.parse()方法解析了xml文件,mapperLocations屬性是一個數(shù)組類型的屬性,數(shù)組里存儲了xml文件的全路徑。通

過for循環(huán)對每一個xml進行解析。進入parse方法。在進入parse方法前初始化了XMLMapperBuilder并將其configuration屬性設(shè)置為MybatisSqlSessionFactoryBean的configuration屬性屬性。

XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(mapperLocation.getInputStream(),
                            targetConfiguration, mapperLocation.toString(), targetConfiguration.getSqlFragments());

對parse方法進行解析 

public void parse() {
    //判斷是否加載過配置文件
    if (!configuration.isResourceLoaded(resource)) {
      //解析mapper標(biāo)簽
      configurationElement(parser.evalNode("/mapper"));
      //標(biāo)注該配置已經(jīng)被加載過了
      configuration.addLoadedResource(resource);
      //將dao對應(yīng)的類與xml mapper標(biāo)簽的namespaces屬性做綁定
      bindMapperForNamespace();
    }
    parsePendingResultMaps();
    parsePendingCacheRefs();
    parsePendingStatements();
  }

先分析 parse方法里的configurationElement方法。該方法逐步解析mapper標(biāo)簽下的子標(biāo)簽,具體解析過程比較復(fù)雜在此就不分析了。

 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"));
      resultMapElements(context.evalNodes("/mapper/resultMap"));
      sqlElement(context.evalNodes("/mapper/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);
    }
  }

bindMapperForNamespace方法將namespace將生成的的類類型通過

configuration.addMapper(boundType)方法放到Configuration類的MapperRegistry類型屬性mapperRegistry的knownMappers屬性的緩存中(該屬性是一個以類類型key,MapperProxyFactory為value的HashMap)。

private void bindMapperForNamespace() {
    String namespace = builderAssistant.getCurrentNamespace();
    if (namespace != null) {
      Class<?> boundType = null;
      try {
        boundType = Resources.classForName(namespace);
      } catch (ClassNotFoundException e) {
        // ignore, bound type is not required
      }
      if (boundType != null && !configuration.hasMapper(boundType)) {
        // Spring may not know the real resource name so we set a flag
        // to prevent loading again this resource from the mapper interface
        // look at MapperAnnotationBuilder#loadXmlResource
        configuration.addLoadedResource("namespace:" + namespace);
        configuration.addMapper(boundType);
      }
    }
  }

到此這篇關(guān)于Mybatis sql與xml文件讀取方法詳細(xì)分析的文章就介紹到這了,更多相關(guān)Mybatis sql與xml文件讀取內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java序列化機制詳解

    Java序列化機制詳解

    Java 序列化機制是一種將對象轉(zhuǎn)換為字節(jié)流的過程,以便在網(wǎng)絡(luò)上傳輸或保存到文件中,并能在需要時將字節(jié)流還原為對象,這一機制通過實現(xiàn) java.io.Serializable 接口來實現(xiàn),同時涉及到一些關(guān)鍵概念和注意事項,需要的朋友可以參考下
    2023-12-12
  • Java操作數(shù)據(jù)庫連接池案例講解

    Java操作數(shù)據(jù)庫連接池案例講解

    這篇文章主要介紹了Java操作數(shù)據(jù)庫連接池案例講解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • 基于java中反射的總結(jié)分析

    基于java中反射的總結(jié)分析

    所謂反射,就是根據(jù)一個已經(jīng)實例化了的對象來還原類的完整信息
    至少對我而言,我認(rèn)為它帶給我的好處是,讓我從下往上的又了解了一遍面向?qū)ο?/P>

    2013-05-05
  • Spring的自動裝配Bean的三種方式

    Spring的自動裝配Bean的三種方式

    本篇文章主要介紹了 Spring的自動裝配Bean的三種方式,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-02-02
  • java圖形界面之布局設(shè)計

    java圖形界面之布局設(shè)計

    這篇文章主要介紹了java圖形界面之布局設(shè)計的相關(guān)資料,需要的朋友可以參考下
    2015-06-06
  • 如何解決Gradle、Maven項目build后沒有mybatis的mapper.xml文件的問題

    如何解決Gradle、Maven項目build后沒有mybatis的mapper.xml文件的問題

    這篇文章主要介紹了如何解決Gradle、Maven項目build后沒有mybatis的mapper.xml文件的問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • 詳解springboot讀取yml配置的幾種方式

    詳解springboot讀取yml配置的幾種方式

    這篇文章主要介紹了詳解springboot讀取yml配置的幾種方式,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10
  • 深入了解HttpClient的ResponseHandler接口

    深入了解HttpClient的ResponseHandler接口

    這篇文章主要為大家介紹了深入了解HttpClient的ResponseHandler接口,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-10-10
  • Java的Servlet及其生命周期詳解

    Java的Servlet及其生命周期詳解

    這篇文章主要介紹了Java的Servlet及其生命周期詳解,Servlet是用Java編寫的服務(wù)器端程序,一門用于開發(fā)動態(tài)web資源的技術(shù),其主要功能在與交互式的瀏覽和修改數(shù)據(jù),生成動態(tài)web內(nèi)容,需要的朋友可以參考下
    2023-11-11
  • myeclipse安裝Spring Tool Suite(STS)插件的方法步驟

    myeclipse安裝Spring Tool Suite(STS)插件的方法步驟

    這篇文章主要介紹了myeclipse安裝Spring Tool Suite(STS)插件的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08

最新評論

大厂| 泰兴市| 天祝| 六枝特区| 左权县| 从化市| 鸡泽县| 龙川县| 濮阳县| 三台县| 商南县| 游戏| 壶关县| 松溪县| 荔浦县| 灵丘县| 方城县| 普格县| 广安市| 乌兰县| 阿拉善左旗| 中方县| 武胜县| 灵川县| 阳朔县| 鄄城县| 南通市| 红桥区| 通渭县| 阿合奇县| 沭阳县| 永清县| 吴堡县| 怀来县| 革吉县| 个旧市| 米泉市| 水城县| 九江县| 饶河县| 保山市|