我正在使用通过搜索和StackOverflow中的示例找到的常见FieldSetMapper逻辑,我遇到了让我感到惊讶的情况。要么它是一个功能,要么是一个bug,但我想我会在这里进行审核,看看别人如何处理它。
使用Spring Batch,我有一个管道分隔文件,它有字符串和数字值,可以根据位置选择。例如:
string|string|number|number|string
string||number||string
在实现FieldSetMapper的字段集映射器类中,通常会执行一些映射,例如:
newThingy.setString1(fieldSet.readString("string1"));
newThingy.setString2(fieldSet.readString("string2"));
newThingy.setValue1(fieldSet.readInt("value1"));
newThingy.setValue2(fieldSet.readInt("value2"));
newThingy.setString3(fieldSet.readString("string3"));
在测试过程中,上面第1行的代码工作正常。 对于具有string2和value的空值的第2行,抛出了数字而不是字符串的Java异常:
Caused by: java.lang.NumberFormatException: Unparseable number:
at org.springframework.batch.item.file.transform.DefaultFieldSet.parseNumber(DefaultFieldSet.java:754)
at org.springframework.batch.item.file.transform.DefaultFieldSet.readInt(DefaultFieldSet.java:323)
at org.springframework.batch.item.file.transform.DefaultFieldSet.readInt(DefaultFieldSet.java:335)
at com.healthcloud.batch.mapper.MemberFieldSetMapper.mapFieldSet(MemberFieldSetMapper.java:31)
at com.healthcloud.batch.mapper.MemberFieldSetMapper.mapFieldSet(MemberFieldSetMapper.java:1)
我在Spring Batch提供的DefaultFieldSetMapper.java类中做了一些研究,它实现了FieldSet类来试图理解发生了什么。
我发现readString调用的readAndTrim函数如果读取的值为空则返回null
protected String readAndTrim(int index) {
String value = tokens[index];
if (value != null) {
return value.trim();
}
else {
return null;
}
}
...但是当使用readInt(或许还有其他)时,我们会返回一个异常。
private Number parseNumber(String candidate) {
try {
return numberFormat.parse(candidate);
}
catch (ParseException e) {
throw new NumberFormatException("Unparseable number: " + candidate);
}
}
我确实看到在某些方法中可以返回默认值的位置,但显然不允许使用null。我期望的是FieldSet实现中的所有方法之间的一致行为,它允许在读取数据时将文件与我的数据库匹配。分隔和固定长度文件中的空白值相当常见。
如果无法正确处理基于数字的值,我可能必须将所有内容转换为String,因为它被读取然后经历麻烦到手动处理转换到数据库,这显然违背了使用Spring Batch的目的。
我错过了一些我应该处理得更好的东西吗?如果需要,我可以添加更多代码,我只觉得这是常用的,我可以保持这个简短。将根据需要进行编辑。
编辑:添加有关为Spring Batch类找到的单元测试的信息
测试用例状态中的注释应该设置默认值,但为什么呢?我不想要默认。我的数据库允许在Integer列中使用空值。我必须将默认设置为某个任意数字,希望没有人发送,在插入之前检查它,然后在插入时切换为null。我仍然不喜欢这个“功能”。
@Test
public void testReadBlankInt() {
// Trying to parse a blank field as an integer, but without a default
// value should throw a NumberFormatException
try {
fieldSet.readInt(13);
fail();
}
catch (NumberFormatException ex) {
// expected
}
try {
fieldSet.readInt("BlankInput");
fail();
}
catch (NumberFormatException ex) {
// expected
}
}
答案 0 :(得分:0)
始终健全检查您的输入/数据。我通常会将Util类与所需的所有解析/读取/验证结合在一起。下面的裸骨版......
public static Integer getInteger(FieldSet fs, String key, Integer default) {
if(StringUtils.isNumeric(fs.readString(key)) {
return fs.readInt(key);
} else {
return default;
}
}