使用DBUnit框架数据库插入特殊字符失败的查错经历
本文記錄的是使用DBUnit測試框架進行數據庫數據插入時,插入特殊字符失敗的查錯經歷。希望能對向我這樣的小白同學們在遇到類似問題時,能夠有一些啟發。
背景:
在寫跟數據庫交互模塊的單元測試,數據庫表中的ext字段,需要先寫入數據,然后再讀取出來,進行處理。ext字段格式是key1CTRL^Dvalue1CTRL^CKey2CTRL^Dvalue2。使用DBUnit框架來做單元測試,DBUnit是一個基于junit擴展的數據庫測試框架。此次項目里插入數據庫的數據是以xml形式的文件來組織的。xml文件的部分內容如下
在Java中,CTRL^D的值是(char)4,CTRL^C的值是(char)3。此處普及下Java代碼中字符串\u0003的意思,就是說Unicode值(char)3轉義之后的值。在單元測試中,發現數據庫中讀取出的數據,本來一個字符 CTRL^C 即 \u0003 變成了6個字符,分別是\,u,0,0,0,3.
排查問題的過程:
既然數據庫里讀取出的值不對,說明插入的值就是錯的。首先不太了解Java,沒有仔細看import到單元測試里的包,沒有發現使用了junit框架和DBUnit。導致盲目找了一會兒同事開發的DBUnitBaseTest這個單元測試基類的問題,認為就是轉碼的問題。無果,后來看到了這個基類DBUniteBaseTest的源碼,才知道有DBUnit這個東東,而且發現基類沒做什么特殊處理,就是根據配置文件初始化DataSource,然后根據xml數據文件向數據庫中對應表插入數據的過程。
后來在google里搜索,用的關鍵詞就是dbunit \u0003 之類的,太具體了,導致沒有查到太多相關的有用信息。一直苦于找不到解決問題的思路。
后來有同事提醒可以用CDATA,查了一下CDATA的用法,有了一些思路。
"CDATA是在XML文檔里面使用的關鍵字,用來告訴XML解析器,這部分內容不用解析,是給其他程序用的,比如JAVASCRIPT等等。在XML文檔中的所有文本都會被解析器解析,只有在CDATA部件之內的文本會被解析器忽略。"
后來又從上面的搜索結果的網頁里看到了一個有用的東東:numeric character reference.
Because XML syntax uses some characters for tags and attributes it is not possible to directly use those characters inside XML tags or attribute values. To include special characters inside XM files you must use the numeric character reference instead of that character. The numeric character reference must be UTF-8 because the supported encoding for XML files is defined in the prolog as encoding=“UTF-8” and should not be changed.
The numeric character reference uses the format:
&#nn; decimal form
&#xhh; hexadeciaml form
于是就有了以下的方案:
1.嘗試直接寫 \u0004的 numeric character,就是  失敗,報的錯誤是: Character reference "" is an invalid XML character
2.\u0004中,只把 \ 用numeric character代替了,即\ u0004 這個方式仍然是6個字符,跟直接寫 \u0004 一樣的效果
3. 使用 CDATA: ext=<![CDATA["postage\u000410.0\u0003"]]> 發現寫法可能不對,報錯是xml的格式出錯。
這個時候,感覺自己快接近真相了,就是感覺每次搜索\u0004相關的東西,范圍太小了,不太能找到問題的答案。后來跟同事聊這個問題,同事提到就是這些控制字符沒有正確編碼,一下子就把我點醒了。直接搜 does xml support control characters,有如下發現:
Specifically, 0x1-0x1F and 0x7F-0x9F must be encoded as escapes in XML 1.1. The former were forbidden and the latter were optionally not-escaped in 1.0.
所以可以看到,采用方案1時,由于XML1.0不支持這幾個控制字符,所以仍然報錯,而且是說這個字符是非法的XML字符。從上面的搜索結果里看,XML 1.1 支持這幾個控制字符,于是很開心的把xml文件中的xml版本由1.0改成1.1,結果還是報錯了:
org.dbunit.dataset.DataSetException: Line 1: XML version "1.1" is not supported, only XML 1.0 is supported.
最后使出了簡單粗暴的解決辦法:對于這張表的這個字段,直接使用DataSource, 然后用Statement執行sql語句來進行數據的更新,更新為我們想要的字段。
PS:后來又遇到了在java的properties文件里,如果有中文,程序中解析出來是亂碼的問題。查看了一下同事寫的單元測試的基類DBUnitTest的代碼,發現properties文件是通過Properties類來加載的 prop.load(new FileInputStream(file))。搜索了一下Properties類的load函數的定義,發現是因為
The input stream is in a simple line-oriented format as specified in load(Reader) and is assumed to use the ISO 8859-1 character encoding;
?
轉載于:https://www.cnblogs.com/Jack47/p/control-characters-in-dbunit-xml.html
總結
以上是生活随笔為你收集整理的使用DBUnit框架数据库插入特殊字符失败的查错经历的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: gitlab git clone 卡住_
- 下一篇: 主存储器物理地址,逻辑地址,转换