最简单的数据抽取就是把目标源中所需要的数据抽取到自己的数据库中。只要知道数据库表中的字段然后select、insert就OK了
因为项目的需求,无法确定目标源中表中字段是我们所需要的,如果代码中写死,后期可能需要改动代码,所以此处把代码写灵活一点避免后期频繁的改动代码。
Spring boot 的经常用到的配置文件是application.yml 或是application.properties,此处我用的是application.yml。
两种配置文件的区别请参考:
https://blog.csdn.net/weixin_30666943/article/details/97737922?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522158501880219724847036587%2522%252C%2522scm%2522%253A%252220140713.130056874..%2522%257D&request_id=158501880219724847036587&biz_id=0&utm_source=distribute.pc_search_result.none-task
这里自定义配置文件: dbConfig.properties
在自定义配置文件中定义号自己要抽取目标源表的表名,字段名。
然后用PropertiesUtil类去获取配置文件中的信息。
package com.bug.demo.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.Objects;
import java.util.Properties;
代码如下:
/**
* @author bughuang
* @version 1.0
* @date 2020/3/16 12:32
*/
public class PropertiesUtil {
private static Logger log = LoggerFactory.getLogger(PropertiesUtil.class);
private static Properties props;
//resource文件夹内读取
static {
String fileName = "dbConfig.properties";
props = new Properties();
try {
props.load(new InputStreamReader(Objects.requireNonNull(PropertiesUtil.class.getClassLoader().
getResourceAsStream(fileName)), StandardCharsets.UTF_8));
} catch (IOException e) {
log.error("配置文件读取异常", e);
}
}
/**
* 根据配置文件中的key获取value
* @param key
* @return
*/
public static String getProperty(String key) {
String value = props.getProperty(key.trim());
if (StringUtils.isEmpty(value)) {
return null;
}
return value.trim();
}
/**
* 根据配置文件中的key获取value (当获取不到值赋予默认值)
* @param key
* @param defaultValue
* @return
*/
public static String getProperty(String key, String defaultValue) {
String value = props.getProperty(key.trim());
if (StringUtils.isEmpty(value)) {
value = defaultValue;
}
return value.trim();
}
}
自定义配置文件及如何获取内容:
https://blog.csdn.net/qq_35387940/article/details/90714123
另外也可以通过自定义.yml文件用注解读取如:
https://blog.csdn.net/tyrant_800/article/details/78780312?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522158497595819724848305578%2522%252C%2522scm%2522%253A%252220140713.130056874..%2522%257D&request_id=158497595819724848305578&biz_id=0&utm_source=distribute.pc_search_result.none-task
这里就不再多叙述了。
SELECT nextval('USER_SEQ_ID')
insert into target (id,user_name,sex,age,phone,email,unit_name,duty_name,user_id,insert_time)
values
(nextval('USER_SEQ_ID'),
#{item.userName,jdbcType=VARCHAR},
#{item.sex,jdbcType=VARCHAR},
#{item.age,jdbcType=VARCHAR},
#{item.phone,jdbcType=VARCHAR},
#{item.email,jdbcType=VARCHAR},
#{item.unitName,jdbcType=VARCHAR},
#{item.dutyName,jdbcType=VARCHAR},
#{item.userId,jdbcType=VARCHAR},
#{item.insertTime,jdbcType=VARCHAR})
这样可以解决字段名改变只需要修改配置文件就可以抽取一个表中其他字段。
注意:这里必须是抽取的结果集一定,就是想要的字段数量固定。但如果一旦表中的关联关系改变就无法满足。 此时就可以在配置文件中加入sql语句,然后mybatis中传递sql。还是要注意结果集必须是确定的。
现在我改变了配置文件中的配置:
然后执行得到:
以上两个步骤可以完成批量的抽取,但是在项目中有时需要增量抽取数据入库。
项目中用的数据库是postgresql,网上查看的增量抽取的方法都需要在源数据库上安装插件。这里不符合项目情况,所以只能自己开发。此下的方法应该适合所有的数据库。
表结构如下:
每次需要更新数据的时候查询一下log表如果表中没有该张表的数据,则是批量插入,如果有就是增量插入。如果是增量插入需要根据Log表中存储的data_type 判断是时间还是根据id。然后出最后一条记录,取出data_index的值。更具data_index的值在查询的时候增加查询条件。
每次根据源数据库跟新数据到自己的数据库中,数据更新完毕时插入数据到Log中记录插入的时间及表名等信息。
SELECT nextval('LOG_SEQ_ID')
insert into t_data_log (id, data_type, data_index,
update_time, is_delete,table_name)
values (nextval('LOG_SEQ_ID'),
#{dataType,jdbcType=VARCHAR}, #{dataIndex,jdbcType=VARCHAR},
#{updateTime,jdbcType=VARCHAR}, #{isDelete,jdbcType=VARCHAR},
#{tableName,jdbcType=VARCHAR})
设置定时任务每5分钟执行一次。
设置定时任务的步骤如下:
@EnableScheduling
@EnableAsync
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* @author bughuang
* @version 1.0
* @date 2020/3/19 17:42
*/
@Component
@Slf4j
public class AsyncTask {
@Resource
private EtlController etlController;
@Scheduled(cron = "${cron}")
//定时任务需要返回值的情况
public void task4() {
long begin = System.currentTimeMillis();
ResultModel resultModel = etlController.EtlTest();
long end = System.currentTimeMillis();
log.info("任务查询更新数据耗时="+(end-begin)+"结果是:"+resultModel);
}
}
并加上@ Component
@Scheduled(cron = "${cron}")
Spring boot 定时任务请参考:
https://blog.csdn.net/qq_32120667/article/details/96477237?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522158504116719726867834561%2522%252C%2522scm%2522%253A%252220140713.130056874..%2522%257D&request_id=158504116719726867834561&biz_id=0&utm_source=distribute.pc_search_result.none-task