SpringBatch結(jié)合SpringBoot簡(jiǎn)單使用實(shí)現(xiàn)工資發(fā)放批處理操作方式
最近有接觸到批處理相關(guān)的需求,學(xué)習(xí)了下SpringBatch的使用方法。SpringBatch能把復(fù)雜的批處理任務(wù)進(jìn)行step分解,并能通過reader和writer滿足不同來源數(shù)據(jù)的處理需求,支持在step定義時(shí)設(shè)置異常重試策略等,比較方便拓展。
簡(jiǎn)單記錄下基于SpringBoot寫的使用demo。
需求
兩張表,user_with_role和role_num,分別有user信息和工資流水信息,role_num冗余。
user_with_role表,包含員工信息和role字段信息
CREATE TABLE `user_with_role` ( `id` INT NOT NULL AUTO_INCREMENT, `username` VARCHAR(45) NULL, `role` VARCHAR(45) NULL, PRIMARY KEY (`id`));
role_num表,包含發(fā)錢信息
CREATE TABLE `role_num1` ( `id` INT NOT NULL AUTO_INCREMENT, `role` VARCHAR(45) NULL, `account` INT NULL, `username` VARCHAR(45) NULL, `inputtime` VARCHAR(45) NULL, PRIMARY KEY (`id`));
pom設(shè)置和application配置文件
在springboot的基礎(chǔ)上使用batch,pom.xml中增加dependency
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-batch</artifactId>
</dependency>還需要加上jdbc依賴,不過這個(gè)一般都有加。
application中增加:
spring:
batch:
initialize-schema: always這個(gè)配置主要是讓springbatch自動(dòng)在數(shù)據(jù)庫中創(chuàng)建運(yùn)行所需的表,SpringBoot2.7版本后修改為 spring.batch.jdbc.initialize-schema 了,不過我還在用老土2.3,先這樣吧。
bean類
UserWithRole
@Data
public class UserWithRole {
private int id;
private String userName;
private String role;
}RoleNum
@Data
public class RoleNum {
private int id;
private String role;
private int account;
private String userName;
private String inputTime;
}關(guān)鍵job配置類
包含reader,writer,step和整體job的配置,通過@Bean注解的方法來進(jìn)行spring管理,下面一步步來。
@Configuration
@EnableBatchProcessing
// batch job設(shè)置
// 將user_with_role中的role_user工資信息,輸出到role_num表中
public class RoleCountingBatchJobConfig {
//注入任務(wù)對(duì)象工廠
@Autowired
private JobBuilderFactory jobBuilderFactory;
//任務(wù)的執(zhí)行由Step決定,注入step對(duì)象的factory
@Autowired
private StepBuilderFactory stepBuilderFactory;
@Autowired
private DataSource dataSource;
@Autowired
private NamedParameterJdbcTemplate namedParameterJdbcTemplate;SpringBatch默認(rèn)會(huì)構(gòu)建兩個(gè)Factory用來進(jìn)行job構(gòu)建,DataSource默認(rèn)為Spring配置的數(shù)據(jù)庫,NamedParameterJdbcTemplate由Spring提供,用來將statement中的問號(hào)占位符改為利用命名參數(shù)映射更方便,不過我后面沒用。
// 設(shè)置itemReader
@Bean
public JdbcCursorItemReader<UserWithRole> getItemReader(){
JdbcCursorItemReader<UserWithRole> itemReader = new JdbcCursorItemReader<>();
itemReader.setDataSource(dataSource);//設(shè)置數(shù)據(jù)源
// 實(shí)體映射
itemReader.setRowMapper(new RowMapper<UserWithRole>() {
@Override
public UserWithRole mapRow(ResultSet rs, int rowNum) throws SQLException {
UserWithRole uwr = new UserWithRole();
uwr.setId(rs.getInt("id"));
uwr.setUserName(rs.getString("userName"));
uwr.setRole(rs.getString("role"));
return uwr;
}
});
String sql = "select u.id as id, u.username as userName, u.role as role from user_with_role as u";
itemReader.setSql(sql);
return itemReader;
}itemReader 用的是 JdbcCursorItemReader ,用來從user_with_role表中讀取數(shù)據(jù),主要是配置 RowMapper ,將行數(shù)據(jù)封裝成 UserWithRole 對(duì)象,sql就是簡(jiǎn)單查詢。
// 設(shè)置itemWriter
@Bean
public JdbcBatchItemWriter<RoleNum> getItemWriter(){
JdbcBatchItemWriter<RoleNum> itemWriter = new JdbcBatchItemWriter<>();
itemWriter.setDataSource(dataSource);
itemWriter.setJdbcTemplate(namedParameterJdbcTemplate);
String sql = "insert into role_num(role, account, username, inputtime) values(?, ?, ?, ?)";
itemWriter.setSql(sql);
itemWriter.setItemPreparedStatementSetter(new RoleNumPreparedStatementSetter());
return itemWriter;
}itemWriter 用的是 JdbcBatchItemWriter ,用來把RoleNum對(duì)象存到數(shù)據(jù)庫中,主要的參數(shù)寫入邏輯寫在 RoleNumPreparedStatementSetter 類中。
public class RoleNumPreparedStatementSetter implements ItemPreparedStatementSetter<RoleNum> {
// 將role_num的批處理計(jì)算結(jié)果存入的sql
@Override
public void setValues(RoleNum roleNum, PreparedStatement preparedStatement) throws SQLException {
preparedStatement.setString(1, roleNum.getRole());
preparedStatement.setInt(2, roleNum.getAccount());
preparedStatement.setString(3, roleNum.getUserName());
preparedStatement.setString(4, roleNum.getInputTime());
}
}RoleNumPreparedStatementSetter 主要是將參數(shù)通過占位符放到sql中。
// 設(shè)置process
@Bean
public RoleUserCountingProcess getProcess(){
return new RoleUserCountingProcess();
}public class RoleUserCountingProcess implements ItemProcessor<UserWithRole, RoleNum> {
// 將user的信息轉(zhuǎn)換成roleNum信息,當(dāng)作發(fā)工資
@Override
public RoleNum process(UserWithRole userWithRole) throws Exception {
RoleNum newRoleNum = new RoleNum();
newRoleNum.setUserName(userWithRole.getUserName());
newRoleNum.setRole(userWithRole.getRole());
newRoleNum.setInputTime(new LocalDateTime(new Date()).toString());
if(userWithRole.getRole()==null)
return newRoleNum;
switch (userWithRole.getRole()) {
case "employee":
newRoleNum.setAccount(100);
break;
case "manager":
newRoleNum.setAccount(10000);
break;
case "boss":
newRoleNum.setAccount(100000);
break;
}
System.out.println(newRoleNum.getUserName() + "---" + newRoleNum.getAccount());
return newRoleNum;
}
}process中定義了具體的工資寫入邏輯,實(shí)現(xiàn)了 ItemProcess 接口的process方法,將itemReader的輸出UserWithRole類和itemWriter的輸入RoleNum類進(jìn)行連接,從而完成process過程。
// 設(shè)置step
@Bean
public Step getStep(){
return stepBuilderFactory.get("user_role_convert_step")
.<UserWithRole, RoleNum>chunk(10)
.reader(getItemReader())
.processor(getProcess())
.writer(getItemWriter())
.build();
}
// 獲取job對(duì)象
@Bean
public Job RoleCountingBatchJob(JobBuilderFactory jobBuilders,
StepBuilderFactory stepBuilders){
return jobBuilders.get("user_role_convert_step")
.start(getStep())
.build();
}最后定義step和job整體流程。
在配置文件中加入:
spring:
batch:
job:
enabled: false可以阻止job在項(xiàng)目啟動(dòng)時(shí)自動(dòng)執(zhí)行。
controller啟動(dòng)jobInstance
@Controller
public class BatchRunnerController {
@Autowired
JobLauncher jobLauncher;
// 自定義job任務(wù)
@Autowired
Job roleCountingBatchJob;
@RequestMapping("/countingRoleUser")
@ResponseBody
public String countingRollUser() throws JobInstanceAlreadyCompleteException, JobExecutionAlreadyRunningException, JobParametersInvalidException, JobRestartException {
// 設(shè)置時(shí)間parameter來區(qū)分instance
JobParametersBuilder jobParametersBuilder = new JobParametersBuilder();
jobParametersBuilder.addDate("startDate", new Date());
jobLauncher.run(roleCountingBatchJob, jobParametersBuilder.toJobParameters());
return "role user counting batch success --- " +
Objects.requireNonNull(jobParametersBuilder.toJobParameters().getDate("startDate")).toString();
}
}利用 jobLauncher 來執(zhí)行對(duì)應(yīng)的job,date時(shí)間來區(qū)分不同的jobInstance。
實(shí)現(xiàn)效果

user_with_role表

批處理job正常執(zhí)行

duideduide沒有role所以沒發(fā)到工資
總結(jié)
本文簡(jiǎn)單記錄了下簡(jiǎn)單的springbatch的使用,包括item相關(guān),process編寫,step構(gòu)建和最終的job使用。springbatch還有一點(diǎn)是可以設(shè)置出現(xiàn)異常的處理策略,比如容忍數(shù)次異常,調(diào)過某些異常等,在真實(shí)使用中比較靈活,有機(jī)會(huì)再補(bǔ)充。
好了,以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java實(shí)現(xiàn)自定義table寬高的示例代碼
在桌面應(yīng)用、管理系統(tǒng)乃至報(bào)表工具中,表格(JTable)作為最常用的數(shù)據(jù)展示組件,不僅承載對(duì)數(shù)據(jù)的增刪改查,還需要配合布局與視覺需求,而 Java Swing 的 JTable 默認(rèn)行高和列寬均采用系統(tǒng)或 L&F 的默認(rèn)值,所以本文給大家介紹了Java實(shí)現(xiàn)自定義table寬高2025-06-06
你必須得會(huì)的SpringBoot全局統(tǒng)一處理異常詳解
程序在運(yùn)行的過程中,不可避免會(huì)產(chǎn)生各種各樣的錯(cuò)誤,這個(gè)時(shí)候就需要進(jìn)行異常處理,本文主要為大家介紹了SpringBoot實(shí)現(xiàn)全局統(tǒng)一處理異常的方法,需要的可以參考一下2023-06-06
Mybatis實(shí)現(xiàn)關(guān)聯(lián)關(guān)系映射的方法示例
本文主要介紹了Mybatis實(shí)現(xiàn)關(guān)聯(lián)關(guān)系映射的方法示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07
Java abstract class 與 interface對(duì)比
這篇文章主要介紹了 Java abstract class 與 interface對(duì)比的相關(guān)資料,需要的朋友可以參考下2016-12-12
Groovy動(dòng)態(tài)語言使用教程簡(jiǎn)介
這篇文章主要為大家介紹了Groovy動(dòng)態(tài)語言使用教程簡(jiǎn)介,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09
Mybatis plus關(guān)閉駝峰命名的四種方法(防止出現(xiàn)查詢?yōu)镹ull)
這篇文章主要介紹了Mybatis plus關(guān)閉駝峰命名的四種方法(防止出現(xiàn)查詢?yōu)镹ull),數(shù)據(jù)庫的字段命名方式為使用下劃線連接,對(duì)應(yīng)的實(shí)體類應(yīng)該是駝峰命名方式,而我使用的是和數(shù)據(jù)庫同樣的命名方式,需要的朋友可以參考下2022-01-01
MyBatis動(dòng)態(tài)SQL之<choose><when><o(jì)therwise>標(biāo)簽的使用
MyBatis中動(dòng)態(tài)語句choose-when-otherwise 類似于Java中的switch-case-default語句,本文就來介紹一下MyBatis動(dòng)態(tài)SQL之<choose><when><o(jì)therwise>標(biāo)簽的使用,感興趣的可以了解一下2023-09-09
解決IDEA創(chuàng)建第一個(gè)spring boot項(xiàng)目提示cannot resolve xxx等
這篇文章主要介紹了解決IDEA創(chuàng)建第一個(gè)spring boot項(xiàng)目提示cannot resolve xxx等錯(cuò)誤問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01

