1、转换简介
kettle的转换是数据流,比如我们第一个节点叫做生成数据,生成10条数据,那么后面的节点都会执行10次。如果第一个节点生成记录后面跟另一个JS节点,在JS节点又通过putrow 加了2条数据,那么数据集总共会有3条数据,JS节点执行一次,但是JS后的节点会执行3次。
2、实现思路
借助本文章节1中的转换特性,我们比如我们设计一个分页查询入库就可以分为以下几个步骤:
- 生成所需数据 在这里我们可以定义一条数据,确保后面节点可以运行。在这个步骤我们定义2个变量(total,page和pageSize)
- 表输入节点 用于查询总数
- JS节点,用于根据总数和每页多少条生成页码array
javascript
// 必须total有值的才去计算,我们自己生成的记录那个不处理
if(total){
var page_size = 10;
var total_count = total;
var totalPages = parseInt(total_count / page_size);
if (total_count % page_size > 0) totalPages++;
for (var i = 1; i <= totalPages; i++) {
// 输出每一页的页码
putRow( [parseInt(i), page_size] );
}
}
- 经过JS节点后,实际流数据除了我们自己造的那条,数据库里查询出来的那条,还加了很多条进去,就是我们的分页数据
- 接下来通过字段选择值/选择改名值 插件做数据类型转换,因为js只能输出double类型的变量
- 然后跟一个switch case 让pagesize为空的进写日志步骤,其他的进默认步骤
- 在默认步骤中我们能拿到page和pageSize都不是空的数据 走后面正常逻辑就行了,你是htttp调用接口也好,你是分页查数据库也好都行
下面给大家一个KTR代码,大家复制后另存为.ktr用kettle打开就行了。是上面那个实现的一个简单版本的demo。
XML
<?xml version="1.0" encoding="UTF-8"?>
<transformation>
<info>
<name>分页查询单转换实现</name>
<description/>
<extended_description/>
<trans_version/>
<trans_type>Normal</trans_type>
<trans_status>0</trans_status>
<directory>/</directory>
<parameters>
</parameters>
<log>
<trans-log-table>
<connection/>
<schema/>
<table/>
<size_limit_lines/>
<interval/>
<timeout_days/>
<field>
<id>ID_BATCH</id>
<enabled>Y</enabled>
<name>ID_BATCH</name>
</field>
<field>
<id>CHANNEL_ID</id>
<enabled>Y</enabled>
<name>CHANNEL_ID</name>
</field>
<field>
<id>TRANSNAME</id>
<enabled>Y</enabled>
<name>TRANSNAME</name>
</field>
<field>
<id>STATUS</id>
<enabled>Y</enabled>
<name>STATUS</name>
</field>
<field>
<id>LINES_READ</id>
<enabled>Y</enabled>
<name>LINES_READ</name>
<subject/>
</field>
<field>
<id>LINES_WRITTEN</id>
<enabled>Y</enabled>
<name>LINES_WRITTEN</name>
<subject/>
</field>
<field>
<id>LINES_UPDATED</id>
<enabled>Y</enabled>
<name>LINES_UPDATED</name>
<subject/>
</field>
<field>
<id>LINES_INPUT</id>
<enabled>Y</enabled>
<name>LINES_INPUT</name>
<subject/>
</field>
<field>
<id>LINES_OUTPUT</id>
<enabled>Y</enabled>
<name>LINES_OUTPUT</name>
<subject/>
</field>
<field>
<id>LINES_REJECTED</id>
<enabled>Y</enabled>
<name>LINES_REJECTED</name>
<subject/>
</field>
<field>
<id>ERRORS</id>
<enabled>Y</enabled>
<name>ERRORS</name>
</field>
<field>
<id>STARTDATE</id>
<enabled>Y</enabled>
<name>STARTDATE</name>
</field>
<field>
<id>ENDDATE</id>
<enabled>Y</enabled>
<name>ENDDATE</name>
</field>
<field>
<id>LOGDATE</id>
<enabled>Y</enabled>
<name>LOGDATE</name>
</field>
<field>
<id>DEPDATE</id>
<enabled>Y</enabled>
<name>DEPDATE</name>
</field>
<field>
<id>REPLAYDATE</id>
<enabled>Y</enabled>
<name>REPLAYDATE</name>
</field>
<field>
<id>LOG_FIELD</id>
<enabled>Y</enabled>
<name>LOG_FIELD</name>
</field>
<field>
<id>EXECUTING_SERVER</id>
<enabled>N</enabled>
<name>EXECUTING_SERVER</name>
</field>
<field>
<id>EXECUTING_USER</id>
<enabled>N</enabled>
<name>EXECUTING_USER</name>
</field>
<field>
<id>CLIENT</id>
<enabled>N</enabled>
<name>CLIENT</name>
</field>
</trans-log-table>
<perf-log-table>
<connection/>
<schema/>
<table/>
<interval/>
<timeout_days/>
<field>
<id>ID_BATCH</id>
<enabled>Y</enabled>
<name>ID_BATCH</name>
</field>
<field>
<id>SEQ_NR</id>
<enabled>Y</enabled>
<name>SEQ_NR</name>
</field>
<field>
<id>LOGDATE</id>
<enabled>Y</enabled>
<name>LOGDATE</name>
</field>
<field>
<id>TRANSNAME</id>
<enabled>Y</enabled>
<name>TRANSNAME</name>
</field>
<field>
<id>STEPNAME</id>
<enabled>Y</enabled>
<name>STEPNAME</name>
</field>
<field>
<id>STEP_COPY</id>
<enabled>Y</enabled>
<name>STEP_COPY</name>
</field>
<field>
<id>LINES_READ</id>
<enabled>Y</enabled>
<name>LINES_READ</name>
</field>
<field>
<id>LINES_WRITTEN</id>
<enabled>Y</enabled>
<name>LINES_WRITTEN</name>
</field>
<field>
<id>LINES_UPDATED</id>
<enabled>Y</enabled>
<name>LINES_UPDATED</name>
</field>
<field>
<id>LINES_INPUT</id>
<enabled>Y</enabled>
<name>LINES_INPUT</name>
</field>
<field>
<id>LINES_OUTPUT</id>
<enabled>Y</enabled>
<name>LINES_OUTPUT</name>
</field>
<field>
<id>LINES_REJECTED</id>
<enabled>Y</enabled>
<name>LINES_REJECTED</name>
</field>
<field>
<id>ERRORS</id>
<enabled>Y</enabled>
<name>ERRORS</name>
</field>
<field>
<id>INPUT_BUFFER_ROWS</id>
<enabled>Y</enabled>
<name>INPUT_BUFFER_ROWS</name>
</field>
<field>
<id>OUTPUT_BUFFER_ROWS</id>
<enabled>Y</enabled>
<name>OUTPUT_BUFFER_ROWS</name>
</field>
</perf-log-table>
<channel-log-table>
<connection/>
<schema/>
<table/>
<timeout_days/>
<field>
<id>ID_BATCH</id>
<enabled>Y</enabled>
<name>ID_BATCH</name>
</field>
<field>
<id>CHANNEL_ID</id>
<enabled>Y</enabled>
<name>CHANNEL_ID</name>
</field>
<field>
<id>LOG_DATE</id>
<enabled>Y</enabled>
<name>LOG_DATE</name>
</field>
<field>
<id>LOGGING_OBJECT_TYPE</id>
<enabled>Y</enabled>
<name>LOGGING_OBJECT_TYPE</name>
</field>
<field>
<id>OBJECT_NAME</id>
<enabled>Y</enabled>
<name>OBJECT_NAME</name>
</field>
<field>
<id>OBJECT_COPY</id>
<enabled>Y</enabled>
<name>OBJECT_COPY</name>
</field>
<field>
<id>REPOSITORY_DIRECTORY</id>
<enabled>Y</enabled>
<name>REPOSITORY_DIRECTORY</name>
</field>
<field>
<id>FILENAME</id>
<enabled>Y</enabled>
<name>FILENAME</name>
</field>
<field>
<id>OBJECT_ID</id>
<enabled>Y</enabled>
<name>OBJECT_ID</name>
</field>
<field>
<id>OBJECT_REVISION</id>
<enabled>Y</enabled>
<name>OBJECT_REVISION</name>
</field>
<field>
<id>PARENT_CHANNEL_ID</id>
<enabled>Y</enabled>
<name>PARENT_CHANNEL_ID</name>
</field>
<field>
<id>ROOT_CHANNEL_ID</id>
<enabled>Y</enabled>
<name>ROOT_CHANNEL_ID</name>
</field>
</channel-log-table>
<step-log-table>
<connection/>
<schema/>
<table/>
<timeout_days/>
<field>
<id>ID_BATCH</id>
<enabled>Y</enabled>
<name>ID_BATCH</name>
</field>
<field>
<id>CHANNEL_ID</id>
<enabled>Y</enabled>
<name>CHANNEL_ID</name>
</field>
<field>
<id>LOG_DATE</id>
<enabled>Y</enabled>
<name>LOG_DATE</name>
</field>
<field>
<id>TRANSNAME</id>
<enabled>Y</enabled>
<name>TRANSNAME</name>
</field>
<field>
<id>STEPNAME</id>
<enabled>Y</enabled>
<name>STEPNAME</name>
</field>
<field>
<id>STEP_COPY</id>
<enabled>Y</enabled>
<name>STEP_COPY</name>
</field>
<field>
<id>LINES_READ</id>
<enabled>Y</enabled>
<name>LINES_READ</name>
</field>
<field>
<id>LINES_WRITTEN</id>
<enabled>Y</enabled>
<name>LINES_WRITTEN</name>
</field>
<field>
<id>LINES_UPDATED</id>
<enabled>Y</enabled>
<name>LINES_UPDATED</name>
</field>
<field>
<id>LINES_INPUT</id>
<enabled>Y</enabled>
<name>LINES_INPUT</name>
</field>
<field>
<id>LINES_OUTPUT</id>
<enabled>Y</enabled>
<name>LINES_OUTPUT</name>
</field>
<field>
<id>LINES_REJECTED</id>
<enabled>Y</enabled>
<name>LINES_REJECTED</name>
</field>
<field>
<id>ERRORS</id>
<enabled>Y</enabled>
<name>ERRORS</name>
</field>
<field>
<id>LOG_FIELD</id>
<enabled>N</enabled>
<name>LOG_FIELD</name>
</field>
</step-log-table>
<metrics-log-table>
<connection/>
<schema/>
<table/>
<timeout_days/>
<field>
<id>ID_BATCH</id>
<enabled>Y</enabled>
<name>ID_BATCH</name>
</field>
<field>
<id>CHANNEL_ID</id>
<enabled>Y</enabled>
<name>CHANNEL_ID</name>
</field>
<field>
<id>LOG_DATE</id>
<enabled>Y</enabled>
<name>LOG_DATE</name>
</field>
<field>
<id>METRICS_DATE</id>
<enabled>Y</enabled>
<name>METRICS_DATE</name>
</field>
<field>
<id>METRICS_CODE</id>
<enabled>Y</enabled>
<name>METRICS_CODE</name>
</field>
<field>
<id>METRICS_DESCRIPTION</id>
<enabled>Y</enabled>
<name>METRICS_DESCRIPTION</name>
</field>
<field>
<id>METRICS_SUBJECT</id>
<enabled>Y</enabled>
<name>METRICS_SUBJECT</name>
</field>
<field>
<id>METRICS_TYPE</id>
<enabled>Y</enabled>
<name>METRICS_TYPE</name>
</field>
<field>
<id>METRICS_VALUE</id>
<enabled>Y</enabled>
<name>METRICS_VALUE</name>
</field>
</metrics-log-table>
</log>
<maxdate>
<connection/>
<table/>
<field/>
<offset>0.0</offset>
<maxdiff>0.0</maxdiff>
</maxdate>
<size_rowset>10000</size_rowset>
<sleep_time_empty>50</sleep_time_empty>
<sleep_time_full>50</sleep_time_full>
<unique_connections>N</unique_connections>
<feedback_shown>Y</feedback_shown>
<feedback_size>50000</feedback_size>
<using_thread_priorities>Y</using_thread_priorities>
<shared_objects_file/>
<capture_step_performance>N</capture_step_performance>
<step_performance_capturing_delay>1000</step_performance_capturing_delay>
<step_performance_capturing_size_limit>100</step_performance_capturing_size_limit>
<dependencies>
</dependencies>
<partitionschemas>
</partitionschemas>
<slaveservers>
</slaveservers>
<clusterschemas>
</clusterschemas>
<created_user>-</created_user>
<created_date>2026/03/18 13:56:41.476</created_date>
<modified_user>-</modified_user>
<modified_date>2026/03/18 13:56:41.476</modified_date>
<key_for_session_key/>
<is_key_private>N</is_key_private>
</info>
<notepads>
</notepads>
<order>
<hop>
<from>生成所需数据</from>
<to>计算总页数</to>
<enabled>Y</enabled>
</hop>
<hop>
<from>计算总页数</from>
<to>数据类型转换</to>
<enabled>Y</enabled>
</hop>
<hop>
<from>数据类型转换</from>
<to>判断Pagesize是否为空</to>
<enabled>Y</enabled>
</hop>
<hop>
<from>判断Pagesize是否为空</from>
<to>写日志</to>
<enabled>Y</enabled>
</hop>
<hop>
<from>判断Pagesize是否为空</from>
<to>非空的走接口请求</to>
<enabled>Y</enabled>
</hop>
</order>
<step>
<name>生成所需数据</name>
<type>RowGenerator</type>
<description/>
<distribute>Y</distribute>
<custom_distribution/>
<copies>1</copies>
<partitioning>
<method>none</method>
<schema_name/>
</partitioning>
<fields>
<field>
<name>total</name>
<type>Number</type>
<format/>
<currency/>
<decimal/>
<group/>
<nullif>100</nullif>
<length>-1</length>
<precision>-1</precision>
<set_empty_string>N</set_empty_string>
</field>
<field>
<name>pageSize</name>
<type>Number</type>
<format/>
<currency/>
<decimal/>
<group/>
<nullif/>
<length>-1</length>
<precision>-1</precision>
<set_empty_string>N</set_empty_string>
</field>
</fields>
<limit>1</limit>
<never_ending>N</never_ending>
<interval_in_ms>5000</interval_in_ms>
<row_time_field>now</row_time_field>
<last_time_field>FiveSecondsAgo</last_time_field>
<attributes/>
<cluster_schema/>
<remotesteps>
<input>
</input>
<output>
</output>
</remotesteps>
<GUI>
<xloc>112</xloc>
<yloc>176</yloc>
<draw>Y</draw>
</GUI>
</step>
<step>
<name>计算总页数</name>
<type>ScriptValueMod</type>
<description/>
<distribute>Y</distribute>
<custom_distribution/>
<copies>1</copies>
<partitioning>
<method>none</method>
<schema_name/>
</partitioning>
<compatible>N</compatible>
<optimizationLevel>9</optimizationLevel>
<jsScripts>
<jsScript>
<jsScript_type>0</jsScript_type>
<jsScript_name>Script 1</jsScript_name>
<jsScript_script>//Script here
var page_size = 10;
var total_count = total;
var totalPages = parseInt(total_count / page_size);
if (total_count % page_size > 0) totalPages++;
for (var i = 1; i <= totalPages; i++) {
// 输出每一页的页码
putRow( [parseInt(i), page_size] );
}</jsScript_script>
</jsScript>
</jsScripts>
<fields> </fields>
<attributes/>
<cluster_schema/>
<remotesteps>
<input>
</input>
<output>
</output>
</remotesteps>
<GUI>
<xloc>304</xloc>
<yloc>176</yloc>
<draw>Y</draw>
</GUI>
</step>
<step>
<name>数据类型转换</name>
<type>SelectValues</type>
<description/>
<distribute>Y</distribute>
<custom_distribution/>
<copies>1</copies>
<partitioning>
<method>none</method>
<schema_name/>
</partitioning>
<fields>
<select_unspecified>N</select_unspecified>
<meta>
<name>total</name>
<rename>total</rename>
<type>Integer</type>
<length>-2</length>
<precision>-2</precision>
<conversion_mask/>
<date_format_lenient>false</date_format_lenient>
<date_format_locale/>
<date_format_timezone/>
<lenient_string_to_number>false</lenient_string_to_number>
<encoding/>
<decimal_symbol/>
<grouping_symbol/>
<currency_symbol/>
<storage_type/>
</meta>
<meta>
<name>pageSize</name>
<rename>pageSize</rename>
<type>Integer</type>
<length>-2</length>
<precision>-2</precision>
<conversion_mask/>
<date_format_lenient>false</date_format_lenient>
<date_format_locale/>
<date_format_timezone/>
<lenient_string_to_number>false</lenient_string_to_number>
<encoding/>
<decimal_symbol/>
<grouping_symbol/>
<currency_symbol/>
<storage_type/>
</meta>
</fields>
<attributes/>
<cluster_schema/>
<remotesteps>
<input>
</input>
<output>
</output>
</remotesteps>
<GUI>
<xloc>464</xloc>
<yloc>144</yloc>
<draw>Y</draw>
</GUI>
</step>
<step>
<name>判断Pagesize是否为空</name>
<type>SwitchCase</type>
<description/>
<distribute>Y</distribute>
<custom_distribution/>
<copies>1</copies>
<partitioning>
<method>none</method>
<schema_name/>
</partitioning>
<fieldname>pageSize</fieldname>
<use_contains>N</use_contains>
<case_value_type>Integer</case_value_type>
<case_value_format/>
<case_value_decimal/>
<case_value_group/>
<default_target_step>非空的走接口请求</default_target_step>
<cases>
<case>
<value/>
<target_step>写日志</target_step>
</case>
</cases>
<attributes/>
<cluster_schema/>
<remotesteps>
<input>
</input>
<output>
</output>
</remotesteps>
<GUI>
<xloc>640</xloc>
<yloc>128</yloc>
<draw>Y</draw>
</GUI>
</step>
<step>
<name>写日志</name>
<type>WriteToLog</type>
<description/>
<distribute>Y</distribute>
<custom_distribution/>
<copies>1</copies>
<partitioning>
<method>none</method>
<schema_name/>
</partitioning>
<loglevel>log_level_basic</loglevel>
<displayHeader>Y</displayHeader>
<limitRows>N</limitRows>
<limitRowsNumber>0</limitRowsNumber>
<logmessage/>
<fields>
</fields>
<attributes/>
<cluster_schema/>
<remotesteps>
<input>
</input>
<output>
</output>
</remotesteps>
<GUI>
<xloc>832</xloc>
<yloc>128</yloc>
<draw>Y</draw>
</GUI>
</step>
<step>
<name>非空的走接口请求</name>
<type>HTTP</type>
<description/>
<distribute>Y</distribute>
<custom_distribution/>
<copies>1</copies>
<partitioning>
<method>none</method>
<schema_name/>
</partitioning>
<url>http://192.168.0.3:8098/vmock/get/json</url>
<urlInField>N</urlInField>
<urlField/>
<encoding>UTF-8</encoding>
<httpLogin/>
<httpPassword>Encrypted </httpPassword>
<proxyHost/>
<proxyPort/>
<socketTimeout>10000</socketTimeout>
<connectionTimeout>10000</connectionTimeout>
<closeIdleConnectionsTime>-1</closeIdleConnectionsTime>
<lookup>
<arg>
<name>total</name>
<parameter>total</parameter>
</arg>
<arg>
<name>pageSize</name>
<parameter>pageSize</parameter>
</arg>
</lookup>
<result>
<name>result</name>
<code/>
<response_time/>
<response_header/>
</result>
<attributes/>
<cluster_schema/>
<remotesteps>
<input>
</input>
<output>
</output>
</remotesteps>
<GUI>
<xloc>832</xloc>
<yloc>240</yloc>
<draw>Y</draw>
</GUI>
</step>
<step_error_handling>
</step_error_handling>
<slave-step-copy-partition-distribution>
</slave-step-copy-partition-distribution>
<slave_transformation>N</slave_transformation>
<attributes/>
</transformation>