场景
前几天实施给我们提了个问题,说是在使用系统的过程中,在oscar数据库环境下,使用kettle通过表输入组件经过excel输出组件生成excel文件,然后再通过excel输入组件经过表输出组件到另一个库。他们发现数据库中null类型的字段和‘’类型的字段存到目标数据库时都变为了null,而且他们对两种不同类型的值敏感,所以需要保持一致。
分析
1:应该是转到excel后,excel不区分这两种类型导致,然后再存入目标表时,都转化为了null;
2:网上查阅资料得知,kettle针对null和‘’的处理本身就不太友好。
解决方案
1:网上有人给出了一个将kettle.properties中增加
KETTLE_EMPTY_STRING_DIFFERS_FROM_NULL=Y
的配置解决方法,但是我配置了之后发现存到数据库中都变为了‘’,所以还是没解决我的问题。
2:在表输入之后,通过java脚本组件判断相应字段的值,完成后,将null或‘’赋予一个特殊的值,在导入目标表前,再次将值进行判断,从而实现null和‘’的一致性。解决了这个问题。
大概流程如下图:
表输入后代码组件:
表输出前代码组件:
详细代码如下:
// 表输入后的代码
public boolean processRow(StepMetaInterface smi, StepDataInterface sdi) throws KettleException {
if (first) {
first = false;
}
Object[] r = getRow();
if (r == null) {
setOutputDone();
return false;
}
r = createOutputRow(r, data.outputRowMeta.size());
String XXXX_XXX = get(Fields.In, "XXXX_XXX").getString(r);
if(null==XXXX_XXX){
get(Fields.Out, "XXXX_XXX").setValue(r, "1");
}else if("".equals(XXXX_XXX)){
get(Fields.Out, "XXXX_XXX").setValue(r, "2");
}else{
get(Fields.Out, "XXXX_XXX").setValue(r, XXXX_XXX);
}
putRow(data.outputRowMeta, r);
return true;
}
// 表输出前的代码
public boolean processRow(StepMetaInterface smi, StepDataInterface sdi) throws KettleException {
if (first) {
first = false;
}
Object[] r = getRow();
if (r == null) {
setOutputDone();
return false;
}
r = createOutputRow(r, data.outputRowMeta.size());
String XXX_XX = get(Fields.In, "XXX_XX").getString(r);
if("1".equals(XXX_XX)){
get(Fields.Out, "XXX_XX").setValue(r, null);
}else if("2".equals(XXX_XX)){
get(Fields.Out, "XXX_XX").setValue(r, "");
}else{
get(Fields.Out, "XXX_XX").setValue(r, XXX_XX);
}
putRow(data.outputRowMeta, r);
return true;
}