決戰(zhàn)數(shù)據(jù)庫-spring batch(4)數(shù)據(jù)庫到數(shù)據(jù)庫

tags:springbatch


1.引言

上一篇文章《快速使用組件-spring batch(3)讀文件數(shù)據(jù)到數(shù)據(jù)庫》Spring Batch的讀碍庵、處理、寫組件進行了介紹绝编,并且以實際案例使用了FlatFileItemReader讀文本文件恃轩,并把每行數(shù)據(jù)映射為實體,然后使用JdbcBatchItemWriter把實體對象數(shù)據(jù)存儲到MySQL中锌畸。但在數(shù)據(jù)集成的實際應(yīng)用中勇劣,更多的工作是從A數(shù)據(jù)庫到B數(shù)據(jù)庫靖避,數(shù)據(jù)庫之間是異構(gòu)的,數(shù)據(jù)與數(shù)據(jù)的字段定義是不盡相同的比默,因此幻捏,在數(shù)據(jù)同步、數(shù)據(jù)抽取時命咐,需要從源數(shù)據(jù)庫讀取數(shù)據(jù)篡九,經(jīng)過校驗、轉(zhuǎn)換醋奠,過濾榛臼、清洗,然后把數(shù)據(jù)再寫到目標數(shù)據(jù)庫窜司。本文將在上一篇的基礎(chǔ)上沛善,實現(xiàn)數(shù)據(jù)庫到數(shù)據(jù)庫的數(shù)據(jù)同步。簡單來說塞祈,只需要把從文件讀數(shù)據(jù)改為從數(shù)據(jù)庫讀即可金刁。可下載完整示例工程代碼參考

數(shù)據(jù)庫到數(shù)據(jù)庫

2.開發(fā)環(huán)境

  • JDK: jdk1.8
  • Spring Boot: 2.1.4.RELEASE
  • Spring Batch:4.1.2.RELEASE
  • 開發(fā)IDE: IDEA
  • 構(gòu)建工具Maven: 3.3.9
  • 日志組件logback:1.2.3
  • lombok:1.18.6

3.開發(fā)流程

上一篇文章中,已經(jīng)把User數(shù)據(jù)存儲在mytest數(shù)據(jù)庫中尤蛮,本文將以mytest數(shù)據(jù)庫中的test_user表為源數(shù)據(jù)媳友,使用Spring Batch把數(shù)據(jù)同步到目標數(shù)據(jù)庫my_test1,實現(xiàn)MySQLMySQL的同步产捞。注醇锚,若是不同的數(shù)據(jù)庫,在配置多數(shù)據(jù)源時可更改數(shù)據(jù)庫驅(qū)動和連接信息即可坯临。關(guān)鍵代碼如下所示:

關(guān)鍵代碼

3.1 創(chuàng)建目標數(shù)據(jù)庫

MySQL中創(chuàng)建my_test1數(shù)據(jù)庫作為目標數(shù)據(jù)庫搂抒,執(zhí)行示例工程中的sql/my_test1.sql創(chuàng)建用戶表,為簡單起見尿扯,目標數(shù)據(jù)表與源數(shù)據(jù)表數(shù)據(jù)表結(jié)構(gòu)一樣求晶。創(chuàng)建后如下:

目標數(shù)據(jù)庫

3.2 配置多數(shù)據(jù)源

至此,我們的程序涉及三個數(shù)據(jù)庫衷笋,分別是:

  • 用于Spring Batch數(shù)據(jù)存儲的my_spring_batch
  • 源數(shù)據(jù)庫mytest
  • 目標數(shù)據(jù)庫my_test1

因此芳杏,需要先配置多數(shù)據(jù)源,配置方法跟之前一樣辟宗,配置properties文件的數(shù)據(jù)庫連接信息和使用注解進行配置即可爵赵。如下:

application.properties

# spring batch db
spring.datasource.jdbc-url=jdbc:mysql://localhost:3310/my_spring_batch?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&useSSL=false
spring.datasource.username=root
spring.datasource.password=111111
# origin db
spring.origin-datasource.jdbc-url=jdbc:mysql://localhost:3310/mytest?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&useSSL=false
spring.origin-datasource.username=root
spring.origin-datasource.password=111111
# target db
spring.target-datasource.jdbc-url=jdbc:mysql://localhost:3310/my_test1?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&useSSL=false
spring.target-datasource.username=root
spring.target-datasource.password=111111

然后使用注解注入多數(shù)據(jù)源,如下:

DataSourceConfig.java

@Bean("datasource")
@ConfigurationProperties(prefix="spring.datasource")
@Primary
public DataSource batchDatasource() {
    return DataSourceBuilder.create().build();
}

@Bean("originDatasource")
@ConfigurationProperties(prefix="spring.origin-datasource")
public DataSource originDatasource() {
    return DataSourceBuilder.create().build();
}

@Bean("targetDatasource")
@ConfigurationProperties(prefix="spring.target-datasource")
public DataSource targetDatasource() {
    return DataSourceBuilder.create().build();
}

3.3 添加讀數(shù)據(jù)組件JdbcCursorItemReader

從數(shù)據(jù)庫中讀取數(shù)據(jù)泊脐,Spring Batch提供了組件JdbcCursorItemReader空幻,通過它,可以把數(shù)據(jù)庫的數(shù)據(jù)讀取出來容客,然后映射為實體User秕铛,以供后續(xù)開發(fā)。創(chuàng)建方法如下:

@Bean
public ItemReader db2DbItemReader(@Qualifier("originDatasource") DataSource originDatasource) {
    String readSql = " select * from test_user";
    return new JdbcCursorItemReaderBuilder<User>()
            .dataSource(originDatasource).sql(readSql)
            .verifyCursorPosition(false).rowMapper(new UserRowMapper())
            .build();
}

說明:

  • 使用@Qualifier("originDatasource")標識源數(shù)據(jù)庫
  • JdbcCursorItemReaderBuilder用于構(gòu)建JdbcCursorItemReader
  • 讀數(shù)據(jù)的sql語句根據(jù)實際情況編寫即可缩挑,此處是讀取整個表數(shù)據(jù)但两。
  • 需要把數(shù)據(jù)庫映射為實體User,使用UserRowMapper供置,此mapper實現(xiàn)RowMapper接口谨湘,把從數(shù)據(jù)庫讀取的ResultSet映射為User的字段。

3.4 自定義處理組件Db2DbItemProcessor

讀取到數(shù)據(jù)后芥丧,當前的處理是針對title字段紧阔,不為null的則轉(zhuǎn)為大寫即可。如下:

if(Objects.nonNull(title)){
    user.setTitle(title.toUpperCase());
}

3.5 添加寫數(shù)據(jù)組件JdbcBatchItemWriter

寫入數(shù)據(jù)续担,同樣使用JdbcBatchItemWriter組合擅耽,編寫插入sql語句,把實體User數(shù)據(jù)插入到數(shù)據(jù)庫即可赤拒,如下:

@Bean
public ItemWriter db2DbWriter(@Qualifier("targetDatasource") DataSource targetDatasource) {
    String inserSql ="INSERT INTO test_user(id,name,phone,title,email,gender,date_of_birth,sys_create_time,sys_create_user,sys_update_time,sys_update_user) " +
            "VALUES (:id,:name,:phone,:title,:email,:gender,:dateOfBirth,:sysCreateTime,:sysCreateUser,:sysUpdateTime,:sysUpdateUser)";
    return new JdbcBatchItemWriterBuilder<User>()
            .itemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>())
            .sql(inserSql)
            .dataSource(targetDatasource)
            .build();
}

說明:

  • 使用JdbcBatchItemWriterBuilder進行JdbcBatchItemWriter的創(chuàng)建秫筏,設(shè)置插入數(shù)據(jù)庫的sql語句诱鞠,同時指定數(shù)據(jù)源即可。
  • @Qualifier("targetDatasource") DataSource datasource用于指定數(shù)據(jù)源
  • 使用BeanPropertyItemSqlParameterSourceProvider可以直接把讀取的數(shù)據(jù)實體的屬性數(shù)據(jù)作為參數(shù)填充到sql語句中这敬,從而實現(xiàn)數(shù)據(jù)插入操作航夺。

3.6 組裝完整任務(wù)

經(jīng)過上面的操作,可以使用一個java配置崔涂,把讀阳掐、寫、處理組裝成完整的stepjob冷蚂,如下所示(詳細可見示例工程文件):

@Bean
public Job db2DbJob(Step db2DbStep,JobExecutionListener db2DbListener){
    String funcName = Thread.currentThread().getStackTrace()[1].getMethodName();
    return jobBuilderFactory.get(funcName)
            .listener(db2DbListener)
            .flow(db2DbStep)
            .end().build();
}
@Bean
public Step db2DbStep(ItemReader db2DbItemReader ,ItemProcessor db2DbProcessor
        ,ItemWriter db2DbWriter){
    String funcName = Thread.currentThread().getStackTrace()[1].getMethodName();
    return stepBuilderFactory.get(funcName)
            .<User,User>chunk(10)
            .reader(db2DbItemReader)
            .processor(db2DbProcessor)
            .writer(db2DbWriter)
            .build();
}

3.7 測試

參考上一文章的File2DbJobTest缭保,編寫Db2DbJobTest文件即可。如下:

@Test
public void testDb2DbJob() throws JobParametersInvalidException, JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException {
    //構(gòu)建job參數(shù)
    JobParameters jobParameters = JobUtil.makeJobParameters();
    //運行job
    Map<String, Object> stringObjectMap = jobLauncherService.startJob(db2DbJob, jobParameters);
    //測試結(jié)果
    Assert.assertEquals(ExitStatus.COMPLETED,stringObjectMap.get(SyncConstants.STR_RETURN_EXITSTATUS));
}

經(jīng)過此測試蝙茶,可查看到源數(shù)據(jù)庫mytest中的test_user表中的數(shù)據(jù)艺骂,已全部同步到目標庫my_test1中的test_user中。完成數(shù)據(jù)庫到數(shù)據(jù)庫的數(shù)據(jù)同步隆夯。

4.總結(jié)

本文通過簡單的示例钳恕,從源數(shù)據(jù)庫中讀取表數(shù)據(jù),經(jīng)過處理蹄衷,寫入到目標數(shù)據(jù)庫忧额,具體一定的通用性。希望讓大家更深入的了解Spring Batch愧口,并能用到實踐中睦番。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市耍属,隨后出現(xiàn)的幾起案子托嚣,更是在濱河造成了極大的恐慌,老刑警劉巖恬涧,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件注益,死亡現(xiàn)場離奇詭異,居然都是意外死亡溯捆,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門厦瓢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來提揍,“玉大人,你說我怎么就攤上這事煮仇±驮荆” “怎么了?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵浙垫,是天一觀的道長刨仑。 經(jīng)常有香客問我郑诺,道長,這世上最難降的妖魔是什么杉武? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任辙诞,我火速辦了婚禮,結(jié)果婚禮上轻抱,老公的妹妹穿的比我還像新娘飞涂。我一直安慰自己,他們只是感情好祈搜,可當我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布较店。 她就那樣靜靜地躺著,像睡著了一般容燕。 火紅的嫁衣襯著肌膚如雪梁呈。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天蘸秘,我揣著相機與錄音捧杉,去河邊找鬼。 笑死秘血,一個胖子當著我的面吹牛味抖,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播灰粮,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼仔涩,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了粘舟?” 一聲冷哼從身側(cè)響起熔脂,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎柑肴,沒想到半個月后霞揉,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡晰骑,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年适秩,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片硕舆。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡秽荞,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出抚官,到底是詐尸還是另有隱情扬跋,我是刑警寧澤,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布凌节,位于F島的核電站钦听,受9級特大地震影響洒试,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜朴上,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一垒棋、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧余指,春花似錦捕犬、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至淮韭,卻和暖如春垢粮,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背靠粪。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工蜡吧, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人占键。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓昔善,卻偏偏與公主長得像,于是被迫代替她去往敵國和親畔乙。 傳聞我的和親對象是個殘疾皇子君仆,可洞房花燭夜當晚...
    茶點故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內(nèi)容