数据库迁移——kettle实战(2)

需求:把数据从旧表导入到新表(从oracle到oracle),其中:
1. 字段名字基本全部修改(新表相对于旧表来说)
2. 字段类型部分修改
3. 删除部分字段
4. 增加部分字段
5. 字典字段翻译

对于前两需求,我们可以操作表输入和表输出来进行,大概操作界面如图1和图3

数据库迁移——kettle实战(2)_第1张图片

图1——表输入界面

其中需要注意的地方就是左边箭头所指向的sql语句,因为对于需求2,我们需要对一些字段进行转化,因为旧表为VARCHAR类型,新表为TIMESTAMP类型,所以在表输出时就进行转化,然后我们可以点一下下面的预览(图1没有把那个按钮截取到,抱歉)
这时为了方便测试我们控制sql语句只显示前几行然后如图所示
数据库迁移——kettle实战(2)_第2张图片

图2——表输入预览界面

看来效果还不错,然后针对需求2我们还需要在表输出时使新旧字段进行匹配。

如下图:

数据库迁移——kettle实战(2)_第3张图片

图3——表输出界面

其中值得注意的地方就是:
与表输入不同,表输出要多配置一个“目标表”,因为表输入的“目标表”的配置环节已经包含在了sql语句中的from语句后。

需求一二已经解决,那么我们来看需求三,四。
数据库迁移——kettle实战(2)_第4张图片

图4——新旧对照表的参考图

其中有些在旧表中存在的字段但是新表中没有,有些在新表中有而旧表中没有。但是有个前提,在进行到这个任务时,新表已经建立完成,所以我们面对那些不需要的字段完全可以直接无视,而旧表中没有的我们也不用管。

其中比较复杂的就是最后一个需求,我们需要从原表中某些字段中提取出本来的意思再去字典库进行查找然后转化成新的字段,说白了就是这个字段代表的是一个key-value键值对,我们需要把旧的key换成新的key。那么我们如何来做呢 总不能一个个手工转化吧,kettle当然不会了。

我们在上篇提到过kettle是纯java编写的,它支持java脚本,除此之外还支持js和shell脚本(经过仔细查询发现并不支持python脚本,如果真想用的话可能需要用shell脚本来调用python了=。=,如果你们有好的解决方案可以一起讨论)。
于是我们便有了如下转换图

数据库迁移——kettle实战(2)_第5张图片

图5——总体转换图

这里需要提到的是:第二个环节是为了增加新表中的序列,让每次数据导入时都会相对上条语句进行递增,也是就相当于“主键”的概念。(当然前提是要有这张表的SEQ)

那么java代码要怎么写呢,下面贴出部分代码,对,用到的就是hashmap


import java.util.Arrays;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
    // 定义字典缓存Map
    // 最高学历
    public static Map ZGXLMap = new HashMap();
    // 职称
    public static Map ZCMap = new HashMap();
    // 职务
    public static Map ZWMap = new HashMap();
    // 职业
    public static Map ZYMap = new HashMap();

    public boolean processRow(StepMetaInterface smi, StepDataInterface sdi) throws KettleException {
        if (first) {
            first = false;

        }

        Object[] r = getRow();

        if (r == null) {
            setOutputDone();
            return false;
        }

        // 获取要翻译字典的代码
        String zgxl = get(Fields.In, "zgxl").getString(r);
        String zc = get(Fields.In, "zc").getString(r);
        String zw = get(Fields.In, "zw").getString(r);
        String zy = get(Fields.In, "zy").getString(r);
//logBasic("zgxl:"+zgxl);
//logBasic("zc:"+zc);

        // It is always safest to call createOutputRow() to ensure that your
        // output row's Object[] is large
        // enough to handle any new fields you are creating in this step.
        r = createOutputRow(r, data.outputRowMeta.size());
        // 翻译字典并设置到输出字段中
        get(Fields.Out, "zgxl").setValue(r, ZGXLMap.get(zgxl));
        get(Fields.Out, "zc").setValue(r, ZCMap.get(zc));
        get(Fields.Out, "zw").setValue(r, ZCMap.get(zw));
        get(Fields.Out, "zy").setValue(r, ZYMap.get(zy));

        /*
         * TODO: Your code here. (See Sample)
         * 
         * // Get the value from an input field String foobar = get(Fields.In,
         * "a_fieldname").getString(r);
         * 
         * foobar += "bar";
         * 
         * // Set a value in a new output field get(Fields.Out,
         * "output_fieldname").setValue(r, foobar);
         */
        // Send the row on to the next step.
        putRow(data.outputRowMeta, r);

        return true;
    }

    public boolean init(StepMetaInterface stepMetaInterface, StepDataInterface stepDataInterface) {
        // 最高学历
        ZGXLMap.put("01", "cer_HighestDegree01");
        …………
        ZGXLMap.put("09", "cer_HighestDegree09");
        ZGXLMap.put("10", "cer_HighestDegree10");
        ZGXLMap.put("11", "cer_HighestDegree11");
        // 职称
        ZCMap.put("0101","cer_title_01");
        ZCMap.put("0102","cer_title_02");
        ……
        ……
        //
        return parent.initImpl(stepMetaInterface, stepDataInterface);
    }

如此一来kettle脚本就已经完成了,剩下的就是让它慢慢跑完,胜利就在眼前。。

在接下来的工作中会遇到更多应用到kettle方面的任务,我也会虚心学习,把新的想法和认识写在这里。

你可能感兴趣的:(【Kettle】)