DBunit - 无法将 <1997/02/14> 类型转换为时间戳
DBunit - Unable to typecast <1997/02/14> to TimeStamp
我正在使用 DBUnit (2.49) + Hibernate (4.1.3) 进行集成测试 tutorial。
- 生产数据库:Oracle 10
- 测试数据库:Hsqldb 2.3.3
上下文
我的数据包含日期的当前格式:yyyy/MM/dd
。然而,根据 DBUnit faq,DBUnit 只支持这种格式 yyyy-mm-dd hh:mm:ss.fffffffff
,所以我不得不为 TimeStamp 创建一个新格式。
我是如何修复它的
我根据这个tutorial创建了一个CustomTimeStampDataType
。我更改了这部分:
String formats[] = {"yyyy-MM-dd HH:mm", "yyyy-MM-dd HH:mm a", "yyyy-MM-dd HH:mm:ss.fffffffff"};
进入这个:
String formats[] = {"yyyy/MM/dd"};
- 我按照相同的教程创建了一个
CustomeDataTypeFactory
。我只让它扩展 Oracle10DataTypeFactory
而不是 DefaultDatatTypeFactory
.
在 HibernateDBUnitTestCase
中,我用以下内容覆盖 setDatabaseConfig()
:
@Override
protected void setUpDatabaseConfig(DatabaseConfig config){
config.setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new CustomDataTypeFactory());
}
但是我遇到了新的错误
我 运行 进行单元测试并遇到此错误。
org.dbunit.dataset.datatype.TypeCastException: Unable to typecast value <1997/02/14> of type <java.lang.String> to TIMESTAMP
at org.dbunit.dataset.datatype.TimestampDataType.typeCast(TimestampDataType.java:120)
at org.dbunit.dataset.datatype.TimestampDataType.setSqlValue(TimestampDataType.java:176)
at org.dbunit.database.statement.SimplePreparedStatement.addValue(SimplePreparedStatement.java:73)
at org.dbunit.operation.RefreshOperation$RowOperation.execute(RefreshOperation.java:189)
at org.dbunit.operation.RefreshOperation.execute(RefreshOperation.java:113)
at org.dbunit.AbstractDatabaseTester.executeOperation(AbstractDatabaseTester.java:190)
at org.dbunit.AbstractDatabaseTester.onSetup(AbstractDatabaseTester.java:103)
at org.dbunit.DatabaseTestCase.setUp(DatabaseTestCase.java:156)
at test.HibernateDbUnitTestCase.setUp(HibernateDbUnitTestCase.java:85)
at test.PlayerTest.setUp(PlayerTest.java:117)
Caused by: java.lang.IllegalArgumentException: Timestamp format must be yyyy-mm-dd hh:mm:ss[.fffffffff]
at java.sql.Timestamp.valueOf(Unknown Source)
at org.dbunit.dataset.datatype.TimestampDataType.typeCast(TimestampDataType.java:116)
... 20 more
这很奇怪,好像我的 CustomTimeStamp 没有被调用,所以我使用默认格式更改了数据集中的日期:1997-02-14 00:00:00.0,然后 运行 再次进行单元测试。然后我得到:
org.dbunit.dataset.datatype.TypeCastException: Unable to typecast value <1997-02-14 00:00:00.0> of type <java.lang.String> to TIMESTAMP
at test.CustomTimestampDataType.typeCast(CustomTimestampDataType.java:69)
at test.CustomTimestampDataType.setSqlValue(CustomTimestampDataType.java:84)
at org.dbunit.database.statement.SimplePreparedStatement.addValue(SimplePreparedStatement.java:73)
at org.dbunit.operation.RefreshOperation$RowOperation.execute(RefreshOperation.java:189)
at org.dbunit.operation.RefreshOperation.execute(RefreshOperation.java:113)
at org.dbunit.AbstractDatabaseTester.executeOperation(AbstractDatabaseTester.java:190)
at org.dbunit.AbstractDatabaseTester.onSetup(AbstractDatabaseTester.java:103)
at org.dbunit.DatabaseTestCase.setUp(DatabaseTestCase.java:156)
at test.HibernateDbUnitTestCase.setUp(HibernateDbUnitTestCase.java:85)
at test.PlayerTest.setUp(PlayerTest.java:117)
这意味着 CustomTimeStamp 实际上被调用了 。看起来,问题源于 DatabaseTestCase.setUp,它以某种方式调用了错误的 TimeStampDataType。
我该如何解决这个问题?
我的第一个选择是使用正则表达式将数据集中的每个 yyyy/MM/dd
替换为 yyyy-mm-dd
。这工作正常,直到我不得不测试一种根据请求选择日期的方法(因此格式为 yyyy-mm-dd)并将其与当前日期进行比较。 (所以格式是 yyyy / mm / dd)。 hsqldb无法比较两个不同格式的日期。
我的第二个选择是反编译dbunit.jar,根据教程重写TimeStampDataType。我不熟悉字节码编写,所以在进入未知领域之前,我想知道您是否有其他解决方案。
提前致谢
已修复!
所以我最终选择了第二个选项。
这是详细的路径给需要的人。
- 下载
dbUnit.2.2.source.jar
- 解压缩 jar
- 转到 Eclipse,
File > New > Java Project
- 取消选中
"Use default location"
- 在位置中:指定从 jar 创建的新文件夹的路径
- 点击
Finish
修改TimestampDataType.java(如果需要)
而不是 ts = java.sql.Timestamp.valueOf(stringValue);
使用下面的代码
String formats[] =
{"dd/MM/yyyy HH:mm:ss.SS"}; //and more depending on your need
Timestamp ts = null;
for (int i = 0; i < formats.length; i++)
{
SimpleDateFormat sdf = new SimpleDateFormat(formats[i]);
try {
java.util.Date date = sdf.parse(stringValue);
ts = new Timestamp(date.getTime());
return ts;
}
catch( ParseException e) {
}
修改DateDataType.java(如果需要)
而不是 return java.sql.Date.valueOf(stringValue);
,使用下面的代码
String formats[] =
{"dd/MM/yyyy"}; //and more depending on your need
for (int i = 0; i < formats.length; i++)
{
SimpleDateFormat sdf = new SimpleDateFormat(formats[i]);
try {
java.util.Date date = sdf.parse(stringValue);
java.sql.Date datesql = new java.sql.Date(date.getTime());
return datesql;
}
catch( ParseException e) {
}
}
- 右键单击您的项目,然后
Export
- Select
JAR file
,然后Next
- 然后填写导出目的地
Finish
。
- 您只需将这个新的 jar 添加到库中即可使其正常工作。
我正在使用 DBUnit (2.49) + Hibernate (4.1.3) 进行集成测试 tutorial。
- 生产数据库:Oracle 10
- 测试数据库:Hsqldb 2.3.3
上下文
我的数据包含日期的当前格式:yyyy/MM/dd
。然而,根据 DBUnit faq,DBUnit 只支持这种格式 yyyy-mm-dd hh:mm:ss.fffffffff
,所以我不得不为 TimeStamp 创建一个新格式。
我是如何修复它的
我根据这个tutorial创建了一个
CustomTimeStampDataType
。我更改了这部分:String formats[] = {"yyyy-MM-dd HH:mm", "yyyy-MM-dd HH:mm a", "yyyy-MM-dd HH:mm:ss.fffffffff"};
进入这个:
String formats[] = {"yyyy/MM/dd"};
- 我按照相同的教程创建了一个
CustomeDataTypeFactory
。我只让它扩展Oracle10DataTypeFactory
而不是DefaultDatatTypeFactory
. 在
HibernateDBUnitTestCase
中,我用以下内容覆盖setDatabaseConfig()
:@Override protected void setUpDatabaseConfig(DatabaseConfig config){ config.setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new CustomDataTypeFactory()); }
但是我遇到了新的错误
我 运行 进行单元测试并遇到此错误。
org.dbunit.dataset.datatype.TypeCastException: Unable to typecast value <1997/02/14> of type <java.lang.String> to TIMESTAMP
at org.dbunit.dataset.datatype.TimestampDataType.typeCast(TimestampDataType.java:120)
at org.dbunit.dataset.datatype.TimestampDataType.setSqlValue(TimestampDataType.java:176)
at org.dbunit.database.statement.SimplePreparedStatement.addValue(SimplePreparedStatement.java:73)
at org.dbunit.operation.RefreshOperation$RowOperation.execute(RefreshOperation.java:189)
at org.dbunit.operation.RefreshOperation.execute(RefreshOperation.java:113)
at org.dbunit.AbstractDatabaseTester.executeOperation(AbstractDatabaseTester.java:190)
at org.dbunit.AbstractDatabaseTester.onSetup(AbstractDatabaseTester.java:103)
at org.dbunit.DatabaseTestCase.setUp(DatabaseTestCase.java:156)
at test.HibernateDbUnitTestCase.setUp(HibernateDbUnitTestCase.java:85)
at test.PlayerTest.setUp(PlayerTest.java:117)
Caused by: java.lang.IllegalArgumentException: Timestamp format must be yyyy-mm-dd hh:mm:ss[.fffffffff]
at java.sql.Timestamp.valueOf(Unknown Source)
at org.dbunit.dataset.datatype.TimestampDataType.typeCast(TimestampDataType.java:116)
... 20 more
这很奇怪,好像我的 CustomTimeStamp 没有被调用,所以我使用默认格式更改了数据集中的日期:1997-02-14 00:00:00.0,然后 运行 再次进行单元测试。然后我得到:
org.dbunit.dataset.datatype.TypeCastException: Unable to typecast value <1997-02-14 00:00:00.0> of type <java.lang.String> to TIMESTAMP
at test.CustomTimestampDataType.typeCast(CustomTimestampDataType.java:69)
at test.CustomTimestampDataType.setSqlValue(CustomTimestampDataType.java:84)
at org.dbunit.database.statement.SimplePreparedStatement.addValue(SimplePreparedStatement.java:73)
at org.dbunit.operation.RefreshOperation$RowOperation.execute(RefreshOperation.java:189)
at org.dbunit.operation.RefreshOperation.execute(RefreshOperation.java:113)
at org.dbunit.AbstractDatabaseTester.executeOperation(AbstractDatabaseTester.java:190)
at org.dbunit.AbstractDatabaseTester.onSetup(AbstractDatabaseTester.java:103)
at org.dbunit.DatabaseTestCase.setUp(DatabaseTestCase.java:156)
at test.HibernateDbUnitTestCase.setUp(HibernateDbUnitTestCase.java:85)
at test.PlayerTest.setUp(PlayerTest.java:117)
这意味着 CustomTimeStamp 实际上被调用了 。看起来,问题源于 DatabaseTestCase.setUp,它以某种方式调用了错误的 TimeStampDataType。
我该如何解决这个问题?
我的第一个选择是使用正则表达式将数据集中的每个
yyyy/MM/dd
替换为yyyy-mm-dd
。这工作正常,直到我不得不测试一种根据请求选择日期的方法(因此格式为 yyyy-mm-dd)并将其与当前日期进行比较。 (所以格式是 yyyy / mm / dd)。 hsqldb无法比较两个不同格式的日期。我的第二个选择是反编译dbunit.jar,根据教程重写TimeStampDataType。我不熟悉字节码编写,所以在进入未知领域之前,我想知道您是否有其他解决方案。
提前致谢
已修复!
所以我最终选择了第二个选项。 这是详细的路径给需要的人。
- 下载
dbUnit.2.2.source.jar
- 解压缩 jar
- 转到 Eclipse,
File > New > Java Project
- 取消选中
"Use default location"
- 在位置中:指定从 jar 创建的新文件夹的路径
- 点击
Finish
修改TimestampDataType.java(如果需要)
而不是
ts = java.sql.Timestamp.valueOf(stringValue);
使用下面的代码String formats[] = {"dd/MM/yyyy HH:mm:ss.SS"}; //and more depending on your need Timestamp ts = null; for (int i = 0; i < formats.length; i++) { SimpleDateFormat sdf = new SimpleDateFormat(formats[i]); try { java.util.Date date = sdf.parse(stringValue); ts = new Timestamp(date.getTime()); return ts; } catch( ParseException e) { }
修改DateDataType.java(如果需要)
而不是
return java.sql.Date.valueOf(stringValue);
,使用下面的代码String formats[] = {"dd/MM/yyyy"}; //and more depending on your need for (int i = 0; i < formats.length; i++) { SimpleDateFormat sdf = new SimpleDateFormat(formats[i]); try { java.util.Date date = sdf.parse(stringValue); java.sql.Date datesql = new java.sql.Date(date.getTime()); return datesql; } catch( ParseException e) { } }
- 右键单击您的项目,然后
Export
- Select
JAR file
,然后Next
- 然后填写导出目的地
Finish
。 - 您只需将这个新的 jar 添加到库中即可使其正常工作。