便捷的數(shù)據(jù)讀寫-spring batch(5)結(jié)合beetlSql進(jìn)行數(shù)據(jù)讀寫

tags: springbatch


1.引言

上一篇文章《決戰(zhàn)數(shù)據(jù)庫-spring batch(4)數(shù)據(jù)庫到數(shù)據(jù)庫》使用Spring Batch內(nèi)置的讀郎哭、寫組件贤斜,對(duì)數(shù)據(jù)庫間的數(shù)據(jù)進(jìn)行同步。相對(duì)來說,這個(gè)數(shù)據(jù)讀取和數(shù)據(jù)寫入是基于jdbc進(jìn)行讀寫的(數(shù)據(jù)對(duì)象的映射需要我們自己處理尺上,如UserRowMapper)金顿,我們現(xiàn)在開發(fā)一般都使用上層一點(diǎn)的ORM框架仿荆,如Hibernate,MyBatis,BeetlSQL。對(duì)于Hibernate,Spring Batch有默認(rèn)的HibernateCursorItemReaderHibernateItemWriter坏平,也可以實(shí)現(xiàn)自行使用MyBatisBeetlSQL拢操。個(gè)人感覺,從易用性和學(xué)習(xí)曲線上看舶替,BeetlSQL會(huì)更容易上手令境,社區(qū)也挺活躍,因此顾瞪,本文介紹一下使用Spring Batch結(jié)合BeetlSQL進(jìn)行數(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
  • BeetlSQL: 1.1.77.RELEASE
  • 開發(fā)IDE: IDEA
  • 構(gòu)建工具M(jìn)aven: 3.3.9
  • 日志組件logback:1.2.3
  • lombok:1.18.6

3.BeetlSQL簡要說明

按官方文檔,BeetlSQL是一個(gè)全功能DAO工具陈醒, 同時(shí)具有Hibernate優(yōu)點(diǎn) & Mybatis優(yōu)點(diǎn)功能惕橙,適用于承認(rèn)以SQL為中心,同時(shí)又需求工具能自動(dòng)能生成大量常用的SQL的應(yīng)用钉跷。詳細(xì)可參考官方文檔弥鹦。從最近一段時(shí)間的使用過程中,感覺從開發(fā)效率爷辙、維護(hù)性彬坏、易用性,都比較優(yōu)秀膝晾。

4.使用BeetlSQL讀寫數(shù)據(jù)庫

本示例依然是基于上一篇文章的示例功能栓始,從源數(shù)據(jù)庫中讀取test_user表的數(shù)據(jù),然后經(jīng)過處理血当,再寫入到目標(biāo)數(shù)據(jù)庫的test_user表中幻赚。只是不是使用Spring Batch內(nèi)置的JdbcCursorItemReaderJdbcBatchItemWriter,改為使用BeetlSQL進(jìn)行讀寫歹颓。完整示例可參考代碼

4.1 引入BeetlSQL依賴

BeetlSQL提供了Spring Bootstarter來實(shí)現(xiàn)自動(dòng)配置坯屿,在pom.xml添加以下依賴即可:

<!-- orm框架: beetlsql -->
<dependency>
    <groupId>com.ibeetl</groupId>
    <artifactId>beetl-framework-starter</artifactId>
    <version>1.1.77.RELEASE</version>
</dependency>

添加后,會(huì)添加兩個(gè)依賴巍扛,分別是beetl-2.9.9领跛,和beetlsql-2.11.2,如下圖:

beetlsql

4.2 編寫多數(shù)據(jù)源的dao

4.2.1 添加配置文件

由于我們是使用多數(shù)據(jù)源進(jìn)行讀寫撤奸,關(guān)于多數(shù)據(jù)源的配置吠昭,上一篇文章已經(jīng)進(jìn)行了描述喊括,此處不再說明。BeetlSQL對(duì)多數(shù)據(jù)源有較好的支持矢棚,只需要簡單的配置即可郑什。具體可參考官方文檔。下面對(duì)此做簡單說明蒲肋。在application.properties文件中添加以下配置:

#beetlsql配置
#默認(rèn)/sql蘑拯,可不設(shè)置
#beetlsql.sqlPath=/sql
#dao文件的后綴
beetlsql.daoSuffix=Repository
#自動(dòng)加載和查找的dao文件所在包
beetlsql.basePackage=me.mason.springbatch
#默認(rèn)org.beetl.sql.core.db.MySqlStyle,可不設(shè)置
#beetlsql.dbStyle=org.beetl.sql.core.db.MySqlStyle
#多數(shù)據(jù)源dao文件所在位置兜粘,以包區(qū)分讀寫數(shù)據(jù)源
beetlsql.ds.datasource.basePackage=me.mason.springbatch.dao.local
beetlsql.ds.originDatasource.basePackage=me.mason.springbatch.dao.origin
beetlsql.ds.targetDatasource.basePackage=me.mason.springbatch.dao.target
beetlsql.mutiple.datasource=datasource,originDatasource,targetDatasource

說明:

  • beetlsql.daoSuffix表示Dao文件的后綴申窘,BeetlSql會(huì)根據(jù)此后綴加載Dao
  • beetlsql.mutiple.datasource數(shù)據(jù)源名與數(shù)據(jù)源的配置一致孔轴。

4.2.2 添加dao文件

添加上述配置后剃法,由于使用包名來區(qū)分讀寫數(shù)據(jù)源的Dao,因此需要?jiǎng)?chuàng)建對(duì)應(yīng)的包路鹰,分別在工程中me.mason.springbatch下創(chuàng)建dao.local,dao.origin贷洲,dao.target三個(gè)包,分別存放需要讀取的三個(gè)數(shù)據(jù)源對(duì)應(yīng)的Dao晋柱。在本示例中优构,僅使用源數(shù)據(jù)庫和目標(biāo)數(shù)據(jù)庫,因此雁竞,僅需要在dao.origin中添加OriginUserRepository進(jìn)行源數(shù)據(jù)讀操作俩块,在dao.target中添加TargetUserRepository進(jìn)行寫操作即可。(注意浓领,由于配置中指定是使用后綴Repository玉凯,因此此處的類名需要使用它作為后綴)。如下:

OriginUserRepository.java

@Repository
public interface OriginUserRepository extends BaseMapper<User> {
    List<User> getOriginUser(Map<String,Object> params);
}

TargetUserRepository.java

@Repository
public interface TargetUserRepository extends BaseMapper<User> {
}

說明:

  • 使用注解@Repository標(biāo)注是數(shù)據(jù)讀寫dao
  • 繼承BaseMapper联贩,以使用BeetlSQL內(nèi)置的增刪改查能力
  • 對(duì)于OriginUserRepository漫仆,getOriginUser是自定義的數(shù)據(jù)讀取操作,此操作具體實(shí)現(xiàn)是使用寫在sql/user.md中的sql語句(sql語句在后面將說明)泪幌。

4.3 編寫sql文件

根據(jù)BeetlSql的功能盲厌,開發(fā)者可以自定義sql語句進(jìn)行數(shù)據(jù)庫操作,而sql語句是以markdown文件的形式保存祸泪,支持beetl的語法吗浩,支持參數(shù)化語句,邏輯判斷等操作没隘,這就有點(diǎn)像Mybatis中的xml語句懂扼,但顯示和修改會(huì)更友好。具體sql文件更詳細(xì)的使用功能,讀者可到官文檔查閱阀湿。

本示例中赶熟,上面OriginUserRepository自定義了getOriginUser函數(shù),以此函數(shù)名即可編寫sql進(jìn)行讀數(shù)據(jù)(當(dāng)然陷嘴,由于此sql比較簡單映砖,完全可以不寫到markdown文件也可以實(shí)現(xiàn),此處僅做示例展示此功能而已)灾挨。如下所示:

getOriginUser
===
* 查詢user數(shù)據(jù)

select * from test_user

接著就是寫數(shù)據(jù)需要用到的sql邑退,insertUser是這條語句的名稱,在插入數(shù)據(jù)時(shí)會(huì)使用到:

insertUser
===
* 插入數(shù)據(jù)

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#)

由上面的sql可見劳澄,這跟我們平時(shí)寫sql沒有區(qū)別瓜饥,其中以##包括的是參數(shù),即實(shí)體User的字段浴骂。

4.4 編寫讀組件ItemReader

經(jīng)過上面的配置和添加的dao類,我們已經(jīng)有了讀和寫數(shù)據(jù)的能力宪潮。使用OriginUserRepository溯警,可以編寫Spring BatchItemReader。讀取數(shù)據(jù)后在內(nèi)存中狡相,在read()時(shí)返回梯轻。如下所示:

@Slf4j
public class UserItemReader implements ItemReader<User> {
    protected List<User> items;

    protected Map<String,Object> params;
    @Autowired
    private OriginUserRepository originUserRepository;

    @Override
    public User read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
        if(Objects.isNull(items)){
            //使用beetlsql的md執(zhí)行sql
            items = originUserRepository.getOriginUser(params);
            if(items.size() > 0){
                return items.remove(0);
            }
        }else{
            if (!items.isEmpty()) {
                return items.remove(0);
            }
        }
        return null;
    }

    public Map<String, Object> getParams() {
        return params;
    }

    public void setParams(Map<String, Object> params) {
        this.params = params;
    }
}

說明:

  • originUserRepository.getOriginUser執(zhí)行的是user.mdgetOriginUser查詢語句。
  • 查詢后數(shù)據(jù)保存在List<User>尽棕,在read()時(shí)返回其中的數(shù)據(jù)喳挑。全部返回后會(huì)返回null,以表示結(jié)束滔悉。
  • BeetlSql支持使用Map來傳參伊诵,本示例暫時(shí)沒有使用。

4.5 編寫寫組件ItemWriter

讀取到數(shù)據(jù)后回官,使用TargetUserRepository曹宴,執(zhí)行上面編寫的insertUser來插入數(shù)據(jù)。如下所示

public class UserItemWriter implements ItemWriter<User> {
    @Autowired
    private TargetUserRepository targetUserRepository;

    @Override
    public void write(List<? extends User> items) throws Exception {
        targetUserRepository.getSQLManager().updateBatch("user.insertUser",items);
    }
}

說明:

  • 使用SQLManagerupdateBatch批量寫數(shù)據(jù)
  • user.insertUser中歉提,usermarkdown文件的名稱笛坦,也是實(shí)體名稱,insertUser是寫的sql語句苔巨。

4.6 組裝完整任務(wù)

新建BeetlsqlBatchConfig.java版扩,作為Spring Batch的任務(wù)配置

4.6.1 注入讀寫組件

使用上面已寫的ReaderWriter,使用Bean注解加入侄泽,如下:

@Bean
public ItemReader beetlsqlItemReader() {
    UserItemReader userItemReader = new UserItemReader();
    //設(shè)置參數(shù)礁芦,當(dāng)前示例可不設(shè)置參數(shù)
    Map<String,Object> params = CollUtil.newHashMap();
    userItemReader.setParams(params);
    return userItemReader;
}

@Bean
public ItemWriter beetlsqlWriter() {
    return new UserItemWriter();
}

4.6.2 組裝任務(wù)

使用StepJob,實(shí)現(xiàn)完整的任務(wù)配置悼尾,如下:

@Bean
public Job beetlsqlJob(Step beetlsqlStep,JobExecutionListener beetlsqlListener){
    String funcName = Thread.currentThread().getStackTrace()[1].getMethodName();
    return jobBuilderFactory.get(funcName)
            .listener(beetlsqlListener)
            .flow(beetlsqlStep)
            .end().build();
}
@Bean
public Step beetlsqlStep(ItemReader beetlsqlItemReader ,ItemProcessor beetlsqlProcessor
        ,ItemWriter beetlsqlWriter){
    String funcName = Thread.currentThread().getStackTrace()[1].getMethodName();
    return stepBuilderFactory.get(funcName)
            .<User,User>chunk(10)
            .reader(beetlsqlItemReader)
            .processor(beetlsqlProcessor)
            .writer(beetlsqlWriter)
            .build();
}

4.7 測試

參考上一文章的Db2DbJobTest宴偿,編寫BeetlsqlJobTest文件湘捎。測試前先把目標(biāo)數(shù)據(jù)庫中的test_user庫清空,然后啟動(dòng)Job進(jìn)行測試窄刘,結(jié)果跟Db2DbJobTest是一致的窥妇。日志輸出如下:

result

在上面使用BeetlSql過程中,可見有幾個(gè)好處:

  • 不需要自己寫RowMapper對(duì)數(shù)據(jù)進(jìn)行映射娩践,更簡單活翩。
  • sql語句寫在markdown文件中,修改更靈活翻伺。
  • sql語句執(zhí)行輸出在日志中材泄,更清晰。

5.總結(jié)

本文使用Spring Batch對(duì)數(shù)據(jù)庫到數(shù)據(jù)庫的示例做了一個(gè)改動(dòng)吨岭,使用BeetlSQL進(jìn)行多數(shù)據(jù)源的讀寫操作拉宗,以實(shí)現(xiàn)更簡單、更靈活辣辫、更清晰的數(shù)據(jù)庫讀寫旦事。希望對(duì)想要用Spring Batch同時(shí)又想了解BeetlSql的讀者有幫助。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末急灭,一起剝皮案震驚了整個(gè)濱河市姐浮,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌葬馋,老刑警劉巖卖鲤,帶你破解...
    沈念sama閱讀 206,602評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異畴嘶,居然都是意外死亡蛋逾,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門窗悯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來换怖,“玉大人,你說我怎么就攤上這事蟀瞧〕了蹋” “怎么了?”我有些...
    開封第一講書人閱讀 152,878評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵悦污,是天一觀的道長铸屉。 經(jīng)常有香客問我,道長切端,這世上最難降的妖魔是什么彻坛? 我笑而不...
    開封第一講書人閱讀 55,306評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上昌屉,老公的妹妹穿的比我還像新娘钙蒙。我一直安慰自己,他們只是感情好间驮,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,330評(píng)論 5 373
  • 文/花漫 我一把揭開白布躬厌。 她就那樣靜靜地躺著,像睡著了一般竞帽。 火紅的嫁衣襯著肌膚如雪扛施。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,071評(píng)論 1 285
  • 那天屹篓,我揣著相機(jī)與錄音疙渣,去河邊找鬼。 笑死堆巧,一個(gè)胖子當(dāng)著我的面吹牛妄荔,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播谍肤,決...
    沈念sama閱讀 38,382評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼啦租,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了谣沸?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,006評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤笋颤,失蹤者是張志新(化名)和其女友劉穎乳附,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體伴澄,經(jīng)...
    沈念sama閱讀 43,512評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡赋除,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,965評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了非凌。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片举农。...
    茶點(diǎn)故事閱讀 38,094評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖敞嗡,靈堂內(nèi)的尸體忽然破棺而出颁糟,到底是詐尸還是另有隱情,我是刑警寧澤喉悴,帶...
    沈念sama閱讀 33,732評(píng)論 4 323
  • 正文 年R本政府宣布棱貌,位于F島的核電站,受9級(jí)特大地震影響箕肃,放射性物質(zhì)發(fā)生泄漏婚脱。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,283評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望障贸。 院中可真熱鬧错森,春花似錦、人聲如沸篮洁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽嘀粱。三九已至激挪,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間锋叨,已是汗流浹背垄分。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評(píng)論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留娃磺,地道東北人薄湿。 一個(gè)月前我還...
    沈念sama閱讀 45,536評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像偷卧,于是被迫代替她去往敵國和親豺瘤。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,828評(píng)論 2 345

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