摘要:源碼閱讀之的配置文件所有配置會(huì)被類讀取,我們可以通過此類來了解各個(gè)配置是如何運(yùn)作的。是用于項(xiàng)目中存在多種數(shù)據(jù)庫(kù)時(shí)區(qū)分同一條對(duì)應(yīng)的數(shù)據(jù)庫(kù)??梢赃@樣認(rèn)為,在中的和組合才是一條的唯一標(biāo)識(shí)。如果發(fā)現(xiàn)自己的沒被正確識(shí)別,可以查看方法是否和預(yù)期一致。
MyBatis 源碼閱讀之 databaseId
MyBatis 的配置文件所有配置會(huì)被 org.apache.ibatis.builder.xml.XMLConfigBuilder 類讀取,我們可以通過此類來了解各個(gè)配置是如何運(yùn)作的。而 MyBatis 的映射文件配置會(huì)被 org.apache.ibatis.builder.xml.XMLMapperBuilder 類讀取。我們可以通過此類來了解映射文件的配置時(shí)如何被解析的。
databaseIddatabaseId 是用于項(xiàng)目中存在多種數(shù)據(jù)庫(kù) SQL 時(shí)區(qū)分同一條 SQL 對(duì)應(yīng)的數(shù)據(jù)庫(kù)??梢赃@樣認(rèn)為,在 Mybatis 中 SQL 的 id 和 databaseId 組合才是一條 SQL 的唯一標(biāo)識(shí)。實(shí)際上 MyBatis 只會(huì)選擇性加載指定 databaseId 的 SQL ,還有一些沒有指定 databaseId 的 SQL。這里說的有點(diǎn)不是很準(zhǔn)確,我們來慢慢分析便可以知曉。
databaseId 的配置MyBatis 配置文件中 databaseId 的配置如下:
讀取的代碼如下:
private void databaseIdProviderElement(XNode context) throws Exception { DatabaseIdProvider databaseIdProvider = null; if (context != null) { String type = context.getStringAttribute("type"); // 保持向后兼容 if ("VENDOR".equals(type)) { type = "DB_VENDOR"; } // 屬性設(shè)置 Properties properties = context.getChildrenAsProperties(); // 找到 type 配置對(duì)應(yīng)的類 databaseIdProvider = (DatabaseIdProvider) resolveClass(type).newInstance(); databaseIdProvider.setProperties(properties); } Environment environment = configuration.getEnvironment(); if (environment != null && databaseIdProvider != null) { // 通過數(shù)據(jù)源確定使用的 databaseId ,之后 SQL 也只會(huì)加載這種 databaseId 的 SQL ,其他類型都會(huì)被忽略 String databaseId = databaseIdProvider.getDatabaseId(environment.getDataSource()); configuration.setDatabaseId(databaseId); } }
這里的代碼邏輯比較簡(jiǎn)單:
讀取 databaseIdProvider 節(jié)點(diǎn)的 type 值與子節(jié)點(diǎn)屬性值
根據(jù) type 值找到與之匹配的 DatabaseIdProvider 子類,創(chuàng)建相應(yīng)的實(shí)例,將子節(jié)點(diǎn)屬性設(shè)置到實(shí)例中
調(diào)用 DatabaseIdProvider 實(shí)例的 getDatabaseId() 方法獲取值設(shè)置到 Configuration 實(shí)例中
注:
type 為 DB_VENDOR 表示使用 org.apache.ibatis.mapping.VendorDatabaseIdProvider 作為 DatabaseIdProvider 的實(shí)現(xiàn)類。這一點(diǎn)可以在 org.apache.ibatis.session.Configuration 的構(gòu)造方法中找到證據(jù)。
如果發(fā)現(xiàn)自己的 databaseId 沒被正確識(shí)別,可以查看 getDatabaseId() 方法是否和預(yù)期一致。
databaseId 的使用databaseId 在映射文件里要和上一節(jié)的配置的屬性 value 值對(duì)應(yīng),如下:
讀取的代碼在這,這只是
private void sqlElement(Listlist) throws Exception { if (configuration.getDatabaseId() != null) { // 加載 DataSource 對(duì)應(yīng)的 databaseId 的 SQL 節(jié)點(diǎn) sqlElement(list, configuration.getDatabaseId()); } // 記載 databaseId 為空的 SQL 節(jié)點(diǎn) sqlElement(list, null); } private void sqlElement(List list, String requiredDatabaseId) throws Exception { for (XNode context : list) { String databaseId = context.getStringAttribute("databaseId"); String id = context.getStringAttribute("id"); id = builderAssistant.applyCurrentNamespace(id, false); if (databaseIdMatchesCurrent(id, databaseId, requiredDatabaseId)) { sqlFragments.put(id, context); } } } private boolean databaseIdMatchesCurrent(String id, String databaseId, String requiredDatabaseId) { if (requiredDatabaseId != null) { if (!requiredDatabaseId.equals(databaseId)) { // 兩個(gè) databaseId 一致才會(huì)返回 true,此處不一致 return false; } } else { // 一個(gè)為空,一個(gè)不為空,也不一致 if (databaseId != null) { return false; } // 如果先前已經(jīng)加載過節(jié)點(diǎn),則不再加載 // 是否視為同一個(gè)節(jié)點(diǎn)是由 id 決定 // 但 id 相同,databaseId 不同 mybatis也可以加載,所以有些地方說,id+databaseId 確定唯一一條 SQL if (this.sqlFragments.containsKey(id)) { XNode context = this.sqlFragments.get(id); if (context.getStringAttribute("databaseId") != null) { return false; } } } return true; }
代碼上已經(jīng)有了詳細(xì)的注釋,這里就簡(jiǎn)單說一下。sqlElement() 方法會(huì)被調(diào)用兩次,第一次用于處理 databaseId 與全局 Configuration 實(shí)例的 databaseId 一致的節(jié)點(diǎn);另一次用于處理節(jié)點(diǎn)的 databaseId 為 null 的情況,針對(duì)同一個(gè) id ,優(yōu)先選擇存在 databaseId 并且與數(shù)據(jù)源的一致。
同樣的, 之類的節(jié)點(diǎn)解析代碼也是類似,不過它們的解析代碼在 org.apache.ibatis.builder.xml.XMLStatementBuilder 中。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/72680.html
摘要:配置測(cè)試描述測(cè)試類技術(shù)部查詢表至此初步配置完成執(zhí)行過程獲取解析成接收方法方法方法屬性定位方法數(shù)據(jù)綁定到具體方法提交傳輸獲取配置解析標(biāo)簽對(duì)象獲取過程源碼使用 MyBatis 配置 4.0.0 com.huifer mybatisBook 1.0-SNAPSHOT UTF-8 UTF-8 1...
摘要:原因就是傳入的和原有的單引號(hào),正好組成了,而后面恒等于,所以等于對(duì)這個(gè)庫(kù)執(zhí)行了查所有的操作。類比的執(zhí)行流程和原有的我們使用的方法就是??梢岳斫鉃榫褪怯脕斫馕龆ㄖ频姆?hào)的語(yǔ)句。后續(xù)的流程,就和正常的流程一致了。 前言 在JDBC中,主要使用的是兩種語(yǔ)句,一種是支持參數(shù)化和預(yù)編譯的PrepareStatement,能夠支持原生的Sql,也支持設(shè)置占位符的方式,參數(shù)化輸入的參數(shù),防止Sql注...
摘要:下面我會(huì)詳細(xì)地從源碼的角度分析下文簡(jiǎn)寫成是如何實(shí)現(xiàn)自動(dòng)注入的原理。文件解析器,解析對(duì)應(yīng)的文件信息,并將文件信息注冊(cè)到中。節(jié)點(diǎn)解析器,用于構(gòu)建節(jié)點(diǎn)信息。注冊(cè)與綁定類,將的類信息與綁定。 微信公眾號(hào)「后端進(jìn)階」,專注后端技術(shù)分享:Java、Golang、WEB框架、分布式中間件、服務(wù)治理等等。 老司機(jī)傾囊相授,帶你一路進(jìn)階,來不及解釋了快上車! mybatis-plus是完全基于myba...
摘要:從使用到原理學(xué)習(xí)線程池關(guān)于線程池的使用,及原理分析分析角度新穎面向切面編程的基本用法基于注解的實(shí)現(xiàn)在軟件開發(fā)中,分散于應(yīng)用中多出的功能被稱為橫切關(guān)注點(diǎn)如事務(wù)安全緩存等。 Java 程序媛手把手教你設(shè)計(jì)模式中的撩妹神技 -- 上篇 遇一人白首,擇一城終老,是多么美好的人生境界,她和他歷經(jīng)風(fēng)雨慢慢變老,回首走過的點(diǎn)點(diǎn)滴滴,依然清楚的記得當(dāng)初愛情萌芽的模樣…… Java 進(jìn)階面試問題列表 -...
閱讀 3217·2023-04-26 03:06
閱讀 3699·2021-11-22 09:34
閱讀 1148·2021-10-08 10:05
閱讀 3050·2021-09-22 15:53
閱讀 3552·2021-09-14 18:05
閱讀 1422·2021-08-05 09:56
閱讀 1936·2019-08-30 15:56
閱讀 2137·2019-08-29 11:02