本文记录的是使用DBUnit测试框架进行数据库数据插入时,插入特殊字符失败的查错经历。希望能对向我这样的小白同学们在遇到类似问题时,能够有一些启发。
背景:
在写跟数据库交互模块的单元测试,数据库表中的ext字段,需要先写入数据,然后再读取出来,进行处理。ext字段格式是key1CTRL^Dvalue1CTRL^CKey2CTRL^Dvalue2。使用DBUnit框架来做单元测试,DBUnit是一个基于junit扩展的数据库测试框架。此次项目里插入数据库的数据是以xml形式的文件来组织的。xml文件的部分内容如下

<?xml version="1.0" encoding="utf-8"?>
<dataset>
<feed_item_0007
id="323723909"
biz_number="11223345"
ext="item_price\u0003498.00\u0002postage\u000310.00\u0002location\u0003广州深圳\u0002properties\u0003186026840:125200612;6939376:922305\u0002"
/>
</dataset>

在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,就是 &#4; 失败,报的错误是: Character reference "&#4" 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不支持这几个控制字符,所以仍然报错,而且是说&#4这个字符是非法的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;

使用DBUnit框架数据库插入特殊字符失败的查错经历的更多相关文章

  1. 数据库 插入时 碰到NULL报错判断的一种方法(技巧)

    //public static object ToDBNull(object value) 判断插入数据的时候个别参数不能为空的时候做的判断方法 //{ // if (value == null) / ...

  2. 数据库插入数据失败,log提示不能将值 NULL 插入列 'id'

    已经记不住具体的log信息了,意思就是ID如果没有设置为自增长的情况下就不能插入数据,而建表时ID字段是设置为"not null",所以就不能顺利插入数据. 解决方法有两种: ①建 ...

  3. VS Code编写Python3 insert 数据库插入无效也不报错的坑~.~

    标题最近在开发中需要用到web端开发工具.需要用python工具.偶然发现微软的良心之作:Visual Studio Code,这个大小才几十兆的轻量级代码编辑器,功能却是重量级的,通过插件的方法,, ...

  4. Mybatis 向MySql数据库插入带有日期类型字段的数据

    我们的实体类里面一个字段的日期类型是util.Date,在向数据库插入该实体时会报错,说是 日期哪个字段 Data truncation.所以需要做些更改在mybatis的MAPPER映射文件中对插入 ...

  5. 十三、CI框架之数据库插入操作

    一.CI的数据库插入代码如下: 二.数据库原数据如下: 三.访问网站之后,会显示相关输出 四.我们查看数据库,会增加一条数据 不忘初心,如果您认为这篇文章有价值,认同作者的付出,可以微信二维码打赏任意 ...

  6. uct框架数据库sql文件导入错误之 sql_mode

    uct框架在导入sql文件时可能会出现一种错误 ERROR 1101 (42000): BLOB/TEXT column 'brief' can't have a default value 这是由于 ...

  7. AGS中通过FeatureServer插入数据失败、插入数据在WMTS请求中无法显示以及version概念的讨论

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/. 1.背景 在多个项目中,当我方接口给其他部门人员使用时出现了插入数据失 ...

  8. Laravel框架数据库CURD操作、连贯操作使用方法

    Laravel框架数据库CURD操作.连贯如何来操作了这个操作性是非常的方便简单了我们在这里来为各位介绍一篇相关的教程,具体的细节步骤如下文介绍.   Laravel是一套简洁.优雅的PHP Web开 ...

  9. Laravel框架数据库CURD操作、连贯操作

    这篇文章主要介绍了Laravel框架数据库CURD操作.连贯操作.链式操作总结,本文包含大量数据库操作常用方法,需要的朋友可以参考下 一.Selects 检索表中的所有行 $users = DB::t ...

随机推荐

  1. aa3

    var geoCoordMap = { "海门":[121.15,31.89], "鄂尔多斯":[109.781327,39.608266], "招远 ...

  2. 20145316&20145229实验五:网络通信

    20145316&20145229实验五:网络通信 结对伙伴:20145316 博客链接:http://www.cnblogs.com/xxy745214935/p/6130897.html

  3. Laravel 学习笔记 —— 神奇的服务容器 [转]

    容器,字面上理解就是装东西的东西.常见的变量.对象属性等都可以算是容器.一个容器能够装什么,全部取决于你对该容器的定义.当然,有这样一种容器,它存放的不是文本.数值,而是对象.对象的描述(类.接口)或 ...

  4. Java中有四种常见的Map实现方法

    在 HTML5 之前我们做图片预览主流做法有两种,第一种是通过 Flash 插件来做预览,第二种是 Ajax 实现的假预览,也就是说选择图片文件后,图片其实已经异步上传到服务器,服务器处理后返回图片路 ...

  5. third class

    09remain timer 1.button的背景改变:放在背景图片里面,改变背景图片的位置,这样更简洁 08 simple clock 1.上下padding一样,居中2.setInterval( ...

  6. Codeforces Round #347 (Div. 2) (练习)

    A: 题意:找到[a, b]的最大公约数: 思路:相同时为本身,不同时为1. 套路:碰到水题别想太多: 猜想:两个相邻数,必有一奇一偶,如果偶数有因子3或者其他,奇数可不可能有相同的呢? 枚举一些数后 ...

  7. The Template method pattern

    public class TemplateMethodDemo { public static void main(String[] args) { Teacher test=new Javatrea ...

  8. jsp去掉小数点

    <fmt:formatNumber value="${zyUser.user_gold}" pattern="0"/>

  9. PD4F将HTML转换为PDF乱码问题

    修改pd4fonts.properties文件如下: KaiTi_GB2312=SIMKAI.TTFSimSun=SIMKAI.TTF

  10. rhel7报错整理

    报错现象1: 安装过程需要一段时间,等待完成.   重启后进程     输入 q   再次输入 yes   重启后进入           报错现象2:     挂载镜像后,系统一重启报错:   来自 ...