`
zfanxu
  • 浏览: 126019 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

使用Dbunit+Unitils出现 org.dbunit.dataset.NoSuchColumnException 的解决方法

阅读更多

最近使用dbunit-2.4.8 + Unitils 3.3做DAO层数据库测试的时候

出现如下错误:

 

org.unitils.core.UnitilsException: Error inserting test data from DbUnit dataset for method public void org.zfanxu.test.UserDaoTestWithUnitils.testGetUserById()
	at org.unitils.dbunit.DbUnitModule.insertDataSet(DbUnitModule.java:156)
	at org.unitils.dbunit.DbUnitModule$DbUnitListener.beforeTestSetUp(DbUnitModule.java:557)
	at org.unitils.core.Unitils$UnitilsTestListener.beforeTestSetUp(Unitils.java:273)
	at org.unitils.UnitilsJUnit4TestClassRunner$TestListenerInvokingMethodRoadie.runBeforesThenTestThenAfters(UnitilsJUnit4TestClassRunner.java:151)
	at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:84)
	at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:49)
	at org.unitils.UnitilsJUnit4TestClassRunner.invokeTestMethod(UnitilsJUnit4TestClassRunner.java:95)
	at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:61)
	at org.unitils.UnitilsJUnit4TestClassRunner.access$000(UnitilsJUnit4TestClassRunner.java:44)
	at org.unitils.UnitilsJUnit4TestClassRunner$1.run(UnitilsJUnit4TestClassRunner.java:62)
	at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:34)
	at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:44)
	at org.unitils.UnitilsJUnit4TestClassRunner.run(UnitilsJUnit4TestClassRunner.java:68)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: org.unitils.core.UnitilsException: Error while executing DataSetLoadStrategy
	at org.unitils.dbunit.datasetloadstrategy.impl.BaseDataSetLoadStrategy.execute(BaseDataSetLoadStrategy.java:46)
	at org.unitils.dbunit.DbUnitModule.insertDataSet(DbUnitModule.java:230)
	at org.unitils.dbunit.DbUnitModule.insertDataSet(DbUnitModule.java:153)
	... 18 more
Caused by: org.dbunit.dataset.NoSuchColumnException: user.ID -  (Non-uppercase input column: id) in ColumnNameToIndexes cache map. Note that the map's column names are NOT case sensitive.
	at org.dbunit.dataset.AbstractTableMetaData.getColumnIndex(AbstractTableMetaData.java:117)
	at org.dbunit.operation.AbstractOperation.getOperationMetaData(AbstractOperation.java:89)
	at org.dbunit.operation.AbstractBatchOperation.execute(AbstractBatchOperation.java:140)
	at org.dbunit.operation.CompositeOperation.execute(CompositeOperation.java:79)
	at org.unitils.dbunit.datasetloadstrategy.impl.CleanInsertLoadStrategy.doExecute(CleanInsertLoadStrategy.java:45)
	at org.unitils.dbunit.datasetloadstrategy.impl.BaseDataSetLoadStrategy.execute(BaseDataSetLoadStrategy.java:44)
	... 20 more

 

 

于是在网上google下得知是dbunit的一个bug:http://stackoverflow.com/questions/2210429/dbunit-confusion-over-case-sensitivity-on-table-column-names

 

google上也基本没有可行的解决方案!

 

后来我通过修改dbunit的源代码得以解决,错误的原因是unitils默认使用的是“DefaultMetadataHandler.java”这个类去加载数据库信息,从而得不到数据库schema的值

 

    DefaultMetadataHandler.java

 

boolean areEqual = 
                areEqualIgnoreNull(catalog, catalogName, caseSensitive) &&
                areEqualIgnoreNull(schema, schemaName, caseSensitive) &&
                areEqualIgnoreNull(table, tableName, caseSensitive) &&
                areEqualIgnoreNull(column, columnName, caseSensitive);

 

 这个时候的schemaName是空的,但是传进来的schema是有值的,从而报错!

 

所以解决方法如下:

方法1. 修改DefaultMetadataHandler.java文件将上述代码换成如下代码

 

boolean areEqual = 
                areEqualIgnoreNull(table, tableName, caseSensitive) &&
                areEqualIgnoreNull(column, columnName, caseSensitive);

 

   对,我把catalog和schema的比较都删掉了!

 

方法2: 因为我使用的是mysql数据库,我直接把dbunit中的类"MySqlMetadataHandler"覆盖掉原来的DefaultMetadataHandler.java文件,同样能解决问题

 

最后,也来个抛砖引玉,如果有人有更好的解决方法或是可以不通过修改源代码解决的,可以回复我! :-D

分享到:
评论
5 楼 terrymanu 2013-10-25  
非常感谢楼主抛砖引玉,提供了这个问题的解决方案。
我根据你提供的知识,又仔细看了下源码,找到一个不用修改源码,而是使用扩展的方式修复这个问题。
可以直接覆盖DbUnitModule,重写getDbUnitDatabaseConnection方法,将mysql或者其他数据库需要的MetadataHandler注进去。
我写了一个帖子,详情请见
http://my.oschina.net/u/719192/blog/171387
欢迎交流
4 楼 lfy2008 2013-05-03  
楼主有重新编译的jar包没?发一个 。Unitils3.3的maven地址找不到啊
3 楼 javafansmagic 2012-11-13  
用Unitils 3.3默认依赖的dbunit 2.2.2版本就没有这个问题。
2 楼 zfanxu 2012-07-18  
happyJavaer 写道
求解决方案啊,除了这两种之外楼主想出其他方法了吗?

呵呵,在使用unitils和dbunit整合时,实际使用过程中,并没有想象中的那么方便!
至于这个问题,目前情况下,必须得改源代码实现
1 楼 happyJavaer 2012-07-18  
求解决方案啊,除了这两种之外楼主想出其他方法了吗?

相关推荐

Global site tag (gtag.js) - Google Analytics