之前的博客提到过,kettle的数据抽取主要在于抽取数据,而没有考虑数据库的函数、存储过程、视图、表结构以及索引、约束等,但这些对于数据库来说又是至关重要的,所以我们需要通过修改源码的方式来实现。
具体实现方式为:扩展kettle向导中的多表复制菜单里的功能,在该功能创建的作业中添加节点用于添加输出表的主键和索引。
一、Kettle源码下载
目前我使用的是kettle7.0.0版本,下载的源码版本要与之对应,git下载地址:
https://github.com/pentaho/pentaho-kettle/tree/7.0.0.0-R
在master下选择tags选项卡,选取自己需要的版本:
现在我们拥有了发行版kettle工具和对应的源码,就可以开始进行修改了。
二、Kettle源码运行
1.创建java项目
新建java项目并在项目根目录下建立core,dbdialog,engine,ui,plugins,lib文件夹。
分别将源码目录下的代码拷贝到对应的项目文件下:
拷贝之后各个文件内容如下:
Core,engine,ui,dialog文件内容:
plugins文件内容:
将发行版kettle工具免安装包的lib,libswt,launcher,simple-jndi 四个文件夹拷贝至java项目的根目录,全部拷贝完成后,当前项目根目录下有这些文件:
然后删除lib下的这3个jar包:
选择项目,右键——》Build Path——》Add Libraries——》next——》User Libraries——》New,新建一个library——》选中新建立的library,点击Add JARS——》选中项目下lib目录下的所有jar,以及根据自己电脑型号选择对应的libswt下的swt.jar,点击OK。
比如我的电脑是64位的,就选择win64:
然后选择core、dbdialog、engine、ui四个目录,右键——》Build Path——》Use as Source Folder。
测试是否配置成功,需要找到ui/org/pentaho/di/ui/spoon/Spoon.java,右键运行即可,若出现程序界面,表示配置成功。
三、Kettle源码修改
找到项目目录下的ui/org/pentaho/di/ui/spoon/delegates/SpoonJobDelegate.java方法,这个就是我们主要需要修改的地方。
首先要在这个类的包下面加个工具类用来实现对索引和约束的迁移,工具类代码的git地址如下:
https://gist.github.com/javachen/1564353
修改SpoonJobDelegate.java,在ripDB方法里面添加如下代码(在大约750行左右添加):
Class.forName("com.mysql.jdbc.Driver");
Class.forName("oracle.jdbc.driver.OracleDriver");
String sourceMsg = sourceDbInfo.getHostname() + ":" + sourceDbInfo.getDatabasePortNumberString() + ":" + sourceDbInfo.getDatabaseName();
String targetMsg = targetDbInfo.getHostname() + ":" + targetDbInfo.getDatabasePortNumberString() + "/" + targetDbInfo.getDatabaseName();
Connection sourceCon = DriverManager.getConnection(
"jdbc:oracle:thin:@" + sourceMsg, sourceDbInfo.getUsername(), sourceDbInfo.getPassword());
Connection targetCon = DriverManager.getConnection(
"jdbc:mysql://" + targetMsg, targetDbInfo.getUsername(), targetDbInfo.getPassword());
String pksql = SpoonUtil.exportPkAndIndex(
sourceDbInfo, sourceCon, tables[i],
targetDbInfo, targetCon, tables[i]);
if (!Const.isEmpty(pksql)) {
location.x += 300;
JobEntrySQL jesql = new JobEntrySQL(BaseMessages.getString(PKG,"Spoon.RipDB.AddPkAndIndex")
+ tables[i] + "]");
jesql.setDatabase(targetDbInfo);
jesql.setSQL(pksql);
jesql.setDescription(BaseMessages.getString(PKG,
"Spoon.RipDB.AddPkAndIndex")
+ tables[i]
+ "]");
JobEntryCopy jecsql = new JobEntryCopy();
jecsql.setEntry(jesql);
jecsql.setLocation(new Point(location.x, location.y));
jecsql.setDrawn();
jobMeta.addJobEntry(jecsql);
// Add the hop too...
JobHopMeta jhi = new JobHopMeta(previous, jecsql);
jobMeta.addJobHop(jhi);
previous = jecsql;
}
由于需求就是要把oracle数据库迁移到mysql,我的连接信息直接写死了,如果想灵活获取,也可以自行修改。
修改完成后最好clean一下再运行程序,之前我没有clean,报了找不到文件之类的错误,排查了半天才发现clean一下就解决了······
四、Kettle使用
按照上一篇Kettle文档中的操作,新建Job后建立oracle和mysql的数据库连接,配置mysql的编码,之后选择源数据库和目标数据库,选择需要导入的表,最后输入对应的job名称和存储位置即可生成最新的job:
可以看出,相对于修改之前Job,修改源码之后多出了中间添加主键和索引约束步骤,执行当前Job,就可以将oracle中的主键和索引迁移到mysql了。
本博客参考了以下博客,里面还提到了插件相关的操作:
http://www.zuidaima.com/blog/3670924901010432.htm