[英]Spring Batch job not being called in Spring Boot
我正在嘗試運行 Spring 批處理作業,該作業接收 CSV 文件並將其寫入 HSQL 嵌入式數據庫。 當 CSV 的每一行被添加到數據庫時,我的程序應該記錄,但事實並非如此。運行時我沒有收到任何錯誤,但我知道作業沒有被調用,因為它沒有將任何內容記錄到我的控制台中。
這是我的 BatchConfig.java(定義批處理作業)
package io.davidwilliford.wcdashboard.data;
import javax.sql.DataSource;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.job.builder.JobBuilder;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.batch.item.database.BeanPropertyItemSqlParameterSourceProvider;
import org.springframework.batch.item.database.JdbcBatchItemWriter;
import org.springframework.batch.item.database.builder.JdbcBatchItemWriterBuilder;
import org.springframework.batch.item.file.FlatFileItemReader;
import org.springframework.batch.item.file.builder.FlatFileItemReaderBuilder;
import org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.transaction.PlatformTransactionManager;
import io.davidwilliford.wcdashboard.model.Match;
/**
* Configuration class for our Batch I/O
*
* Reads, Processes and Writes from CSV file
* Called for every line in our CSV
*/
@Configuration
@EnableBatchProcessing
@ComponentScan("io.davidwilliford")
public class BatchConfig {
// includes EVERY field of CSV file
private final String[] FIELD_NAMES = new String[] {
"match", "dayofweek", "match_time", "home_team", "away_team", "home_xg", "away_xg", "score", "attendance",
"venue", "referee", "home_formation", "away_formation", "home_captain", "away_captain", "home_manager",
"away_manager", "home_possession", "away_possession", "home_completed_passes", "home_attempted_pases",
"away_completed_passes", "away_attempted_pases", "home_sot", "away_sot", "home_total_shots",
"away_total_shots", "home_saves", "away_saves", "home_fouls", "away_fouls", "home_corners", "away_corners",
"home_crosses", "away_crosses", "home_touches", "away_touches", "home_tackles", "away_tackles",
"home_interceptions", "away_interceptions", "home_aerials_won", "away_aerials_won", "home_clearances",
"away_clearances", "home_offsides", "away_offsides", "home_gks", "away_gks", "home_throw_ins",
"away_throw_ins", "home_long_balls", "away_long_balls"
};
/**
* Reader
*
* Reads from CSV file
* And turns into MatchInput object
*/
@Bean
public FlatFileItemReader<MatchInput> reader() {
return new FlatFileItemReaderBuilder<MatchInput>()
.name("MatchItemReader")
.resource(new ClassPathResource("match-data.csv"))
.linesToSkip(1)
.delimited()
.names(FIELD_NAMES)
.fieldSetMapper(new BeanWrapperFieldSetMapper<MatchInput>() {
{
setTargetType(MatchInput.class);
}
})
.build();
}
/**
* Processor
*
* Takes in MatchInput objects and makes Match objects
* Is encapsulated into its own class
*/
@Bean
public MatchDataProcessor processor() {
return new MatchDataProcessor();
}
/**
* Writer
*
* Writes the information into Match objects
*/
@Bean
public JdbcBatchItemWriter<Match> writer(DataSource dataSource) {
return new JdbcBatchItemWriterBuilder<Match>()
.itemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>())
.sql("INSERT INTO matches (id, dayofweek, match_time, home_team, away_team, home_score, away_score, attendance, venue, referee, home_captain, away_captain, home_manager, away_manager, home_total_shots, away_total_shots) "
+
"VALUES (:id, :dayofweek, :match_time, :home_team, :away_team, :home_score, :away_score, :attendance, :venue, :referee, :home_captain, :away_captain, : home_manager, :away_manager, :home_total_shots, :away_total_shots)")
.dataSource(dataSource)
.build();
}
/**
* Create a Job whose steps are to Read, Process and Write
*/
@Bean
public Job importUserJob(JobRepository jobRepository, JobCompletionNotificationListener listener, Step step1) {
return new JobBuilder("importUserJob", jobRepository)
.incrementer(new RunIdIncrementer())
.listener(listener)
.flow(step1)
.end()
.build();
}
/**
* This is the step for the above job
* Calls reader, processor and writer (written above)
*/
@Bean
public Step step1(JobRepository jobRepository, PlatformTransactionManager transactionManager,
JdbcBatchItemWriter<Match> writer) {
return new StepBuilder("step1", jobRepository)
.<MatchInput, Match>chunk(10, transactionManager)
.reader(reader())
.processor(processor())
.writer(writer)
.build();
}
}
這是我的 MatchInput.java class
package io.davidwilliford.wcdashboard.data;
/**
* Class for match input
*
* Match will work as our Id
* In total, there are 63 matches
*/
public class MatchInput {
/**
* Class attributes
*/
private String match;
private String dayofweek;
private String match_time;
private String home_team;
private String away_team;
private String home_xg;
private String away_xg;
private String score;
private String attendance;
private String venue;
private String referee;
private String home_formation;
private String away_formation;
private String home_captain;
private String away_captain;
private String home_manager;
private String away_manager;
private String home_possession;
private String away_possession;
private String home_completed_passes;
private String home_attempted_pases;
private String away_completed_passes;
private String away_attempted_pases;
private String home_sot;
private String away_sot;
private String home_total_shots;
private String away_total_shots;
private String home_saves;
private String away_saves;
private String home_fouls;
private String away_fouls;
private String home_corners;
private String away_corners;
private String home_crosses;
private String away_crosses;
private String home_touches;
private String away_touches;
private String home_tackles;
private String away_tackles;
private String home_interceptions;
private String away_interceptions;
private String home_aerials_won;
private String away_aerials_won;
private String home_clearances;
private String away_clearances;
private String home_offsides;
private String away_offsides;
private String home_gks;
private String away_gks;
private String home_throw_ins;
private String away_throw_ins;
private String home_long_balls;
private String away_long_balls;
// purposely left out getters and setters since they arent important
}
這是我的比賽。java model class
package io.davidwilliford.wcdashboard.model;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
/**
* This is the model class for all of our matches
*
* @Entity creates a table with this class
*/
@Entity
@Table(name = "matches")
public class Match {
/**
* Class attributes
*/
@Id
private int id;
private String dayofweek;
private String match_time;
private String home_team;
private String away_team;
private String home_score;
private String away_score;
private String attendance;
private String venue;
private String referee;
private String home_captain;
private String away_captain;
private String home_manager;
private String away_manager;
private String home_total_shots;
private String away_total_shots;
/**
* toString method
*/
@Override
public String toString() {
return "Home Team: " + this.home_team + ", Away Team: " + this.away_team;
}
/**
* Getters and Setters
*/
public long getId() {
}
這是我的 JobCompleteNotificationListener.java class
這個 class 應該在完成后記錄主隊和客隊的名字。
package io.davidwilliford.wcdashboard.data;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobExecutionListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
@Component
public class JobCompletionNotificationListener implements JobExecutionListener {
private static final Logger log = LoggerFactory.getLogger(JobCompletionNotificationListener.class);
private final JdbcTemplate jdbcTemplate;
@Autowired
public JobCompletionNotificationListener(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
/**
* After job is complete,
* Return and print the 2 teams, and the time
*/
@Override
public void afterJob(JobExecution jobExecution) {
if (jobExecution.getStatus() == BatchStatus.COMPLETED) {
log.info("!!! JOB FINISHED! Time to verify the results");
jdbcTemplate.query("SELECT home_team, away_team FROM match",
(rs, row) -> "Home Team: " + rs.getString(1) + " Away Team: "
+ rs.getString(2))
.forEach(str -> System.out.println(str));
}
}
}
當我運行 spring 引導應用程序時,我的控制台中沒有任何記錄。 希望這是足夠的信息,如果需要我可以提供更多。 真誠地感謝任何願意提供幫助的人。
該程序旨在接收 CSV(2022 世界杯信息)並將其嵌入到 Spring 啟動應用程序內的 HSQL 嵌入式數據庫中。 我已按照官方 Spring 引導指南完成 Spring 批處理作業(此處: https://spring.io/guides/gs/batch-processing/ ),但到目前為止運氣不佳。
請檢查“afterJob”方法是否正在執行/發生其他狀態,如 BatchStatus。 棄?
public void afterJob(JobExecution jobExecution) {
if (jobExecution.getStatus() == BatchStatus.ABANDONED) {
...
請嘗試刪除注釋@EnableBatchProcessing
。
當您從 jakarta 命名空間導入時,我假設您使用的是 Spring Boot 3 和 Spring Batch 5。
在 Spring Boot 3 中,Spring Batch 注釋@EnableBatchProcessing
現在具有禁用 Spring Batch 自動配置的效果。 如果您希望公開的Job
在應用程序啟動時自動啟動,那么您缺少的就是這種自動配置。
@Henning 非常感謝! 我很難找到這個,因為https://docs.spring.io/spring-boot/docs/3.0.1/reference/html/howto.html#howto.batch.running-jobs-on-startup仍然聲明使用@啟用批處理。 但是, https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Migration-Guide顯然不鼓勵使用@EnableBatchProcessing。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.