在 ibatis 配置文件修改後生效這個問題上,小朋友我嘗試了不少不科學和科學的方式,經過單元測試 or 各類插件。java
單元測試這一方式我比較推薦,不需花費額外的不少時間,可靠和簡單。python
至於後者呢,前有JRebel、HotCode,後有HotCode2,各類折騰。你要問我爲何不換成 MyBatis,我也不知道。sql
因此小朋友我決定本身作一個,或者說是嘗試,哈哈。服務器
咱們在調用 ibatis 的時候,它在背後是如何工做的?架構
例如最多見的一個 delete 操做:app
(List<DogeDO>) sqlMapClientTemplate.delete(NAMESPACE + 「delete", dogeQuery)框架
在developworks上找到了這樣一張時序圖 [1]svn
顯然,在 SqlMapExecutorDelegate 14 號環節,ibatis 從 MappedStatement 中得到 DeleteStatement,這裏的 Statement,能夠粗鄙的視做真實的 SQL語句,即單元測試
delete * from database;
MappedStatement 是如何初始化的?學習
學習參考文件[2],瞭解到通過一系列的解析以後,經過以下過程
addStatementNodelets { statementParser.parseGeneralStatement { newMappedStatementConfig { delegate.addMappedStatement(mappedStatement) } } }
添加到 mappedStatements 時,進行了鍵值的重複判斷
delegate.addMappedStatement(mappedStatement) { if (mappedStatements.containsKey(ms.getId())) { throw new SqlMapException("There is already a statement named " + ms.getId() + " in this SqlMap."); } }
若是想在 SQL XML 更改以後從新解析並寫入到 mappedStatements,要把這個重複判斷幹掉,須要經過如下的這些空想步驟。
重寫 addMappedStatement
就須要能介入 delegate
就須要能介入 delegate 初始化的地方,即介入 SqlMapClientImpl
就須要能介入 SqlMapClientImpl 初始化的地方,即介入 SqlMapClientFactoryBean
Google和Stackoverflow一通後,發現能夠經過重寫 delegate 等類的方式解決上述問題的,[3]是一個完整的實現,大神啊。
先正向的看看別人作了什麼,能夠用來抄襲
DySqlMapClientFactoryBean
在 SqlMapClientFactoryBean 的基礎上進行了以下擴展:
初始化時將 configLocation、configLocations 保存下來,有何用?
重寫了 buildSqlMapClient 方法,返回重寫後的 DySqlMapClient
DySqlMapClient
對 SqlMapClientImpl 進行了以下擴展:
將超類初始化爲 重寫後的 DySqlMapExecutorDelegate
自行解析 configLocation || configLocations 對應的配置文件,生成 SQL.XML -> SQL_ID 映射關係
DySqlMapExecutorDelegate
對 SqlMapExecutorDelegate 進行了以下擴展:
addMappedStatement,ID值重複時 remove 掉
增長了 checkAndRefreshSqlMap 方法,用來檢查和刷新 Map
重寫各操做實現接口,增長 checkAndRefreshSqlMap 調用
DySqlMapParser
對 SqlMapParser 進行了以下擴展:
增長 resetSqlNodeLets,對 XmlParserState 進行重置。可能會引發 State 混亂
SqlMapConfigUtils
readSqlMapFileMapping,解析包含的 SQL XML 文件列表
readSqlMap,解析每一個 SQL XML 中的 SQL ID
對[3]進行了測試,發現了一個比較重大的不一樣。咱們的工程將 SQL XML 打包成了 jar,而且,即使是現成的文件 ,流程也變成了修改部署 war 包中的 XML 文件,而不是修改源文件,而後直接生效。因此如今面臨了兩個問題。
如何解決 jar 帶來的文件操做
SqlMapFile 直接與源文件關聯
週末撩妹時思考了一下以前遇到的兩個問題
晚間溜達的時候想到的一出,回家實現勉強能用。
中心思想是搭個HTTP服務,將源文件doge.xml資源化爲http://localhost/doge.xml,iBatis刷新時經過文件名構造URL,讀取HTTP資源並進行解析。
改造了一個http server
./http-server /src/main/resources/storage/sqlmap -p 59999 -j true
其實你也能夠用
python -m SimpleHTTPServer 59999
弊端就是每次打開不一樣的工程得本身切到目錄下敲命令啓動服務器
事實上,若是你用 Intellij,默認配置下它會在 63342 端口下啓動一個靜態服務器
路徑在
http://localhost:63342/your-project-home-/very-long-module-path/doge.xml
打完收工
[1] 深刻分析 iBATIS 框架之系統架構與映射原理, http://www.ibm.com/developerworks/cn/java/j-lo-ibatis-principle/
[2] ibatis源碼學習(二)初始化和配置文件解析, http://learnworld.iteye.com/blog/1450057
[3] http://bossbase.googlecode.com/svn/trunk/codecup/src/main/java/com/huawei/boss/ibatis/