kettle 获取查询到变量、结果集、JSON中
目录
一、将查询结果放入变量中
初始化环境,
@Before
public void before() {
try {
// 初始化Kettle环境
KettleEnvironment.init();
EnvUtil.environmentInit();
} catch (KettleException e) {
e.printStackTrace();
}
}
此处的案例模型是如下,从表输入中获取总数据量,然后放在变量节点中,
注意,此处的类型不能设置为Integer,否则会报转换String 到Integer异常。
如下图就是设置变量类型为Integer的报错,
代码如下,
/**
* 获取查询字段值
* @throws KettleException
*/
@Test
public void getVariableFromSQL() throws KettleException{
log.info("start");
//源数据库连接
String mysqL_src = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<connection>" +
"<name>mysqL_src</name>" +
"<server>192.168.10.64</server>" +
"<type>MYSQL</type>" +
"<access>Native</access>" +
"<database>test</database>" +
"<port>3306</port>" +
"<username>root</username>" +
"<password>root</password>" +
"</connection>";
DatabaseMeta srcDatabaseMeta = new DatabaseMeta(mysqL_src);
//创建转换元信息
TransMeta transMeta = new TransMeta();
transMeta.setName("获取查询字段值");
//设置源和目标
transMeta.addDatabase(srcDatabaseMeta);
/*
* 创建 表输入->获取变量
* 同时将两个步骤连接起来
*/
PluginRegistry registry = PluginRegistry.getInstance();
TableInputMeta tableInputMeta = new TableInputMeta();
String tableInputPluginId = registry.getPluginId(StepPluginType.class,
tableInputMeta);
tableInputMeta.setDatabaseMeta(srcDatabaseMeta);
//设置查询条件
String selectSql = "select count(*) as totalNum from user_info_src";
tableInputMeta.setSQL(selectSql);
StepMeta tableInputStep = new StepMeta(tableInputPluginId,
"tableInput", (StepMetaInterface) tableInputMeta);
transMeta.addStep(tableInputStep);
//设置变量步
SetVariableMeta setVariableMeta = new SetVariableMeta();
setVariableMeta.setFieldName(new String[] { "totalNum" });
setVariableMeta.setVariableName(new String[] { "totalNum_var" });
setVariableMeta.setVariableType(new int[] { SetVariableMeta.VARIABLE_TYPE_ROOT_JOB, SetVariableMeta.VARIABLE_TYPE_ROOT_JOB });
setVariableMeta.setDefaultValue(new String[] { "", "" }); //默认值需要设置
//添加步骤到转换中
String setVariablePluginId = registry.getPluginId(StepPluginType.class, setVariableMeta);
StepMeta setVariableStep = new StepMeta(setVariablePluginId, "setVariable", (StepMetaInterface) setVariableMeta);
transMeta.addStep(setVariableStep);
//将步骤和上一步关联起来
transMeta.addTransHop(new TransHopMeta(tableInputStep, setVariableStep));
Trans trans = new Trans(transMeta);
//执行转换
trans.execute(null);
//等待完成
trans.waitUntilFinished();
if (trans.getErrors() > 0) {
System.out.println("交换出错.");
return;
}else{
String totalNumVar = trans.getVariable("totalNum_var");
System.out.println(totalNumVar);
}
}
此处的话是设置一个SetVariableMeta 节点,然后将TableInputMeta的Step和它关联起来,如果要在代码中获取,等trans结束后,如下代码可以获取,
String totalNumVar = trans.getVariable("totalNum_var");
System.out.println(totalNumVar);
不过,如果使用 select id,name from user_info_src这条语句,然后设置变量为id,name时,如果表里有一条数据,那么不会有问题,如果有两条或者以上,那么就报错了,毕竟变量只有一个。
二、 获取查询结果到结果集
结果集这个节点是 RowsToResultMeta ,案例模型如下,当然这里表输入的SQL改成了查询内容,
select id,name from user_info_src
代码的话如下,
/**
* 获取查询结果
* @throws KettleException
*/
@Test
public void getResultFromTrans() throws KettleException{
//源数据库连接
String mysqL_src = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<connection>" +
"<name>mysqL_src</name>" +
"<server>192.168.10.64</server>" +
"<type>MYSQL</type>" +
"<access>Native</access>" +
"<database>test</database>" +
"<port>3306</port>" +
"<username>root</username>" +
"<password>root</password>" +
"</connection>";
DatabaseMeta srcDatabaseMeta = new DatabaseMeta(mysqL_src);
//创建转换元信息
TransMeta transMeta = new TransMeta();
transMeta.setName("获取查询结果");
//设置源和目标
transMeta.addDatabase(srcDatabaseMeta);
/*
* 创建 表输入->表输出
* 同时将两个步骤连接起来
*/
PluginRegistry registry = PluginRegistry.getInstance();
TableInputMeta tableInputMeta = new TableInputMeta();
String tableInputPluginId = registry.getPluginId(StepPluginType.class,
tableInputMeta);
tableInputMeta.setDatabaseMeta(srcDatabaseMeta);
//设置查询条件
String selectSql = "select id,name from user_info_src";
tableInputMeta.setSQL(selectSql);
StepMeta tableInputStep = new StepMeta(tableInputPluginId,
"tableInput", (StepMetaInterface) tableInputMeta);
transMeta.addStep(tableInputStep);
//复制记录到结果
RowsToResultMeta rowsToResultMeta = new RowsToResultMeta();
String rowsToResultMetaPluginId = registry.getPluginId(StepPluginType.class, rowsToResultMeta);
//添加步骤到转换中
StepMeta rowsToResultStep = new StepMeta(rowsToResultMetaPluginId, "rowsToResult", (StepMetaInterface)rowsToResultMeta);
transMeta.addStep(rowsToResultStep);
//添加hop把两个步骤关联起来
transMeta.addTransHop(new TransHopMeta(tableInputStep, rowsToResultStep));
Trans trans = new Trans(transMeta);
//执行转换
trans.execute(null);
//等待完成
trans.waitUntilFinished();
if (trans.getErrors() > 0) {
System.out.println("交换出错.");
return;
}else{
Result result = trans.getResult();
List<RowMetaAndData> rows = result.getRows(); //获取数据
for (RowMetaAndData row : rows) {
RowMetaInterface rowMeta = row.getRowMeta(); //获取列的元数据信息
String[] fieldNames = rowMeta.getFieldNames();
Object[] datas = row.getData();
for (int i = 0; i < fieldNames.length; i++) {
System.out.println(fieldNames[i]+"="+datas[i]);
}
}
}
}
最后输入结果如下,
代码中获取结果集的内容就需要等Trans结束后,使用 Trans.getResult获取,这在以后代码中获取数据很有帮助。
三、将查询结果放入JsonOutputMeta
从标题可以看出,利用的是 JsonOutputMeta ,案例模型的话如下,
下面就直接上代码了,和前两个一样,只不过是把TableInputMeta的后续步骤换为JsonOutputMeta,
/**
* 获取查询为json
* @throws KettleException
*/
@Test
public void getJsonFromSQL() throws KettleException{
//源数据库连接
String mysqL_src = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<connection>" +
"<name>mysqL_src</name>" +
"<server>192.168.10.64</server>" +
"<type>MYSQL</type>" +
"<access>Native</access>" +
"<database>test</database>" +
"<port>3306</port>" +
"<username>root</username>" +
"<password>root</password>" +
"</connection>";
DatabaseMeta srcDatabaseMeta = new DatabaseMeta(mysqL_src);
//创建转换元信息
TransMeta transMeta = new TransMeta();
transMeta.setName("获取查询为json");
//设置源和目标
transMeta.addDatabase(srcDatabaseMeta);
/*
* 创建 表输入->json输出
* 同时将两个步骤连接起来
*/
PluginRegistry registry = PluginRegistry.getInstance();
TableInputMeta tableInputMeta = new TableInputMeta();
String tableInputPluginId = registry.getPluginId(StepPluginType.class,
tableInputMeta);
tableInputMeta.setDatabaseMeta(srcDatabaseMeta);
//设置查询条件
String selectSql = "select id,name from user_info_src";
tableInputMeta.setSQL(selectSql);
StepMeta tableInputStep = new StepMeta(tableInputPluginId,
"tableInput", (StepMetaInterface) tableInputMeta);
transMeta.addStep(tableInputStep);
//Json结果输出
JsonOutputMeta jsonOutputMeta = new JsonOutputMeta();
//此处是输出值
jsonOutputMeta.setOperationType(JsonOutputMeta.OPERATION_TYPE_OUTPUT_VALUE);//这里有三种,写文件,输出值,写文件同时输出值
jsonOutputMeta.setJsonBloc("data");
jsonOutputMeta.setOutputValue("rows");
//设置列
String[] colNames = new String[]{"id","name"};
JsonOutputField[] outputFields = new JsonOutputField[colNames.length];
for(int i = 0; i < colNames.length; i++) {
JsonOutputField field = new JsonOutputField();
String fieldName = colNames[i];
field.setFieldName(fieldName);
field.setElementName(fieldName);
outputFields[i] = field;
}
jsonOutputMeta.setOutputFields(outputFields);
//添加步骤到转换中
String jsonOutputPluginId = registry.getPluginId(StepPluginType.class, jsonOutputMeta);
StepMeta jsonOutputStep = new StepMeta(jsonOutputPluginId, "jsonOutput", (StepMetaInterface)jsonOutputMeta);
transMeta.addStep(jsonOutputStep);
//添加hop把两个步骤关联起来
transMeta.addTransHop(new TransHopMeta(tableInputStep, jsonOutputStep));
Trans trans = new Trans(transMeta);
//执行转换
trans.execute(null);
//等待完成
trans.waitUntilFinished();
if (trans.getErrors() > 0) {
System.out.println("交换出错.");
return;
}else{
}
}
注意此处是输出值,
jsonOutputMeta.setOperationType(JsonOutputMeta.OPERATION_TYPE_OUTPUT_VALUE);
输出结果如下,完全不知道正确与否,那么下面就改为输出json到文件中。
将jsonOutputMeta改写为如下,设置输出文件,
//此处是输出到文件
jsonOutputMeta.setOperationType(JsonOutputMeta.OPERATION_TYPE_WRITE_TO_FILE);//这里有三种,写文件,输出值,写文件同时输出值
jsonOutputMeta.setJsonBloc("data");
// jsonOutputMeta.setOutputValue("rows"); //这个是OPERATION_TYPE_OUTPUT_VALUE,OPERATION_TYPE_BOTH 才有用
jsonOutputMeta.setExtension("txt");
jsonOutputMeta.setFileName("F:\\tmp\\json3");
运行后会生成一个json3.txt文件,如下所示,
这个json3.txt的内容如下,
{
"data": [
{
"name": "测试系统",
"id": "002e7210219b49819ae5485a4d06e3c3"
},
{
"name": "开放资源APP",
"id": "0092d0758f5e4cbb8a54d116e10ae5ed"
}
]
}
也就是说设置的这个jsonOutputMeta.setJsonBloc("data"); 是json的外部信息,那么就可以不设置或者换个名字。
上述setOperationType有三个选项,在spoon中也有三个选项,是对应的,
其实也可以使用如下模型,一边写入到文件中,一边将结果复制到结果集中供后续代码使用数据。