看了网上的一些关于kettle增量更新的文章,实在是没法拿来用啊,不是全量更新,就是要改数据库,一点都不清爽,只能自己整理一下了
kettle安装部署:你们随便找找吧,这里不负责
XxlJob安装部署,自己百度
redis安装部署,自己百度
我只讲kettle和java的整合,因为xxljob可以用定时器来实现,redis也不是必须,不是这次文章的核心,但是我觉得这样搭建的工程最爽
目录
1.进到kettle目录 data-integration,执行 ./spoon.sh 开始启动了
8.代码整合整合,中间排了一下包,特别是javax.servlet-api会有冲突
1.进到kettle目录 data-integration,执行 ./spoon.sh 开始启动了
2.设置jndi
进入kettle 的根目录 data-integration/simple-jndi 修改 jdbc.properties 文件
这个跟我们自己在应用中的配置是一样一样的,比如mysql:
jdbc:mysql://172.10.10.10:3306/test?characterEncoding=utf8&useSSL=true&serverTimezone=Asia/Shanghai&allowMultiQueries=true
live_logging_info/type=javax.sql.DataSource
live_logging_info/driver=org.postgresql.Driver
live_logging_info/url=jdbc:postgresql://localhost:5432/hibernate?searchpath=pentaho_dilogs
live_logging_info/user=hibuser
live_logging_info/password=password
live_logging_info 就是JNDI的名字
3.新建转换
4.在kettle里设置数据库连接
选择数据库类型和连接方式,并设置JNDI 为之前配置好的JNDI,最后别忘记设置共享
5.进入核心对象>>输入>>拖动表输入编辑
此处第四步不确定可以先不加条件,然后点击预览,会不会出来数据,如果有数据再把4的条件加上去
点击预览的效果是这样的,如果没有数据的话,检查表里面是不是没有数据,或者库的名称不对
6.进入核心对象>>输出>>拖动插入/更新,并用连接线连接
7.启动试试,将之前设置的变量值设置一下看看
如果有错误的话看下日志,比如我这个就是表不存在,就要看下输入这里的表是不是能正常执行,修改相应的sql就好了
正确执行是这样的
保存好文件,恭喜,到这里,就完成了一半了,开始上代码
8.代码整合整合,中间排了一下包,特别是javax.servlet-api会有冲突
<dependency>
<groupId>pentaho-kettle</groupId>
<artifactId>kettle-core</artifactId>
<version>9.3.0.0-428</version>
<exclusions>
<exclusion>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
</exclusion>
<exclusion>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>pentaho-kettle</groupId>
<artifactId>kettle-dbdialog</artifactId>
<version>9.3.0.0-428</version>
<exclusions>
<exclusion>
<artifactId>guava</artifactId>
<groupId>com.google.guava</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>pentaho-kettle</groupId>
<artifactId>kettle-engine</artifactId>
<version>9.3.0.0-428</version>
<exclusions>
<exclusion>
<artifactId>hibernate-commons-annotations</artifactId>
<groupId>org.hibernate</groupId>
</exclusion>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</exclusion>
<exclusion>
<groupId>pentaho</groupId>
<artifactId>mondrian</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>pentaho</groupId>
<artifactId>metastore</artifactId>
<version>9.3.0.0-428</version>
</dependency>
kettle:
log-file-path: ./logs/kettle-logs
encoding: utf-8
kettle-home: /Users/xu/resources/kettle/
kettle-jndi-home: /Users/xu/resources/kettle/jndi/
上面那步的home和jndi配合第9步
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import java.nio.charset.Charset;
/**
* 配置在yml文件中的常量数据
*
* @author lyf
*/
@Configuration
@Data
@ConfigurationProperties(prefix = "kettle")
public class KettleConfig {
/**
* 日志文件输出路径
*/
public String logFilePath;
/**
* kettle编码设置
*/
public Charset encoding;
// /**
// * ktr或kjb文件保存路径,单个文件执行的时候需要保存ktr、kjb文件
// */
// public String uploadPath;
/**
* kettle所在路径,初始化会自动生成.kettle文件在该目录,kettle.properties,repositories.xml,shared.xml都在里面
*/
public String kettleHome;
/**
* kettle所在路径,初始化会自动生成.kettle文件在该目录,kettle.properties,repositories.xml,shared.xml都在里面
*/
public String kettleJndiHome;
/**
* kettle插件包所在路径 eg: D:\Development\kettle\8.3\data-integration\plugins
*/
public String kettlePluginPackages;
public String kettlePluginBaseFolder;
// public String kettleLogLevel;
}
@Service
@Slf4j
public class DateSyncJob {
private final String DEFAULT_START_TIME = "2023-09-01 00:00:00";
private final String DEFAULT_START_TIME_KEY = "#1LASTTIME";
@Resource
private RedissonClient redissonClient;
@Autowired
private KettleConfig kettleConfig;
//同步任务
public static final String SYNC_EQUIPMENT_ALARM_RECORD = "SYNC_EQUIPMENT_ALARM_RECORD";
@PostConstruct
public void init() {
try {
//初始化配置文件
log.info("KETTLE HOME:"+kettleConfig.getKettleHome());
Properties properties = System.getProperties();
properties.put("KETTLE_HOME", kettleConfig.getKettleHome());
Const.JNDI_DIRECTORY = kettleConfig.getKettleJndiHome() ;
// 环境
KettleEnvironment.init();
EnvUtil.environmentInit();
log.info("Kettle环境初始化成功");
} catch (Exception e) {
log.error("Kettle环境初始化失败", e);
}
}
/**
* 同步produce_risk_config
*/
@XxlJob(SYNC_PRODUCE_RISK_CONFIG)
public void produceRiskConfigJob() throws KettleException {
sync(SYNC_PRODUCE_RISK_CONFIG,XxlJobHelper.getJobParam(),"produce_risk_config.ktr");
}
/**
* 同步
* @param jobName
* @param jobParam
* @param source
*/
private void sync(String jobName,String jobParam,String source){
String startTime = DEFAULT_START_TIME;
//上次执行时间
String lastTiem = DateUtils.getTime();
String day = DateUtils.getDate();
//如果最后一次执行时间为空,则全量执行一次,否则从上次执行时间开始同步数据,每天全量同步一次
RBucket<String> accessTokenBucket = redissonClient.getBucket(jobName+ day + DEFAULT_START_TIME_KEY);
if(accessTokenBucket.isExists()){
startTime = accessTokenBucket.get();
}
//手动执行的时候
if(StringUtils.isNotBlank(jobParam)){
startTime = jobParam;
}
try {
// ClassPathResource classPathResource = new ClassPathResource(source);
handler(kettleConfig.getKettleHome() + source,startTime);
//将上次执行时间放到缓存
accessTokenBucket.set(lastTiem,2L*24L*60L, TimeUnit.MINUTES);
}catch (Exception e){
log.error("Kettle执行失败:{}", jobName);
log.error(e.getMessage(),e);
}
}
public void handler(String path, String startTime) throws KettleException {
TransMeta tm = new TransMeta(path);
Trans trans = new Trans(tm);
LogChannel logChannel = new LogChannel(trans.getName() + "_" +System.currentTimeMillis());
trans.setLog(logChannel);
//设置参数
trans.setParameterValue("start_time", "'"+startTime+"'");
trans.setVariable("start_time", "'"+startTime+"'");
trans.execute(null);
// 线程等待,直到ktr执行完成
trans.waitUntilFinished();
// 执行完成后获取日志
String logText = KettleLogUtil.getLogText(trans.getLogChannelId(), true, trans.getLogDate().getTime());
log.info("=======>"+logText);
// 判断执行过程中是否有错误, 有错误就抛出错误日志
if (trans.getErrors() > 0) {
throw new KettleException(logText);
}
}
}
这里是通过保存上次同步的时间来进行增量同步,数据库要能查询update_time,否则无法实现
9.配置JNDI和同步文件与代码结合
将jndi和ktr文件放到文件夹里
10.XxlJob的配置,这里可以是定时任务