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)的HibernateCursorItemReader
和HibernateItemWriter
坏平,也可以實(shí)現(xiàn)自行使用MyBatis
和BeetlSQL
拢操。個(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)置的JdbcCursorItemReader
和JdbcBatchItemWriter
,改為使用BeetlSQL
進(jìn)行讀寫歹颓。完整示例可參考代碼
4.1 引入BeetlSQL依賴
BeetlSQL
提供了Spring Boot
的starter
來實(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
,如下圖:
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 Batch
的ItemReader
。讀取數(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.md
的getOriginUser
查詢語句。 - 查詢后數(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);
}
}
說明:
- 使用
SQLManager
的updateBatch
批量寫數(shù)據(jù) -
user.insertUser
中歉提,user
是markdown
文件的名稱笛坦,也是實(shí)體名稱,insertUser
是寫的sql
語句苔巨。
4.6 組裝完整任務(wù)
新建BeetlsqlBatchConfig.java
版扩,作為Spring Batch
的任務(wù)配置
4.6.1 注入讀寫組件
使用上面已寫的Reader
和Writer
,使用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ù)
使用Step
和Job
,實(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
是一致的窥妇。日志輸出如下:
在上面使用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
的讀者有幫助。