在Spring启动中未调用Spring批处理作业



我正在尝试运行一个Spring批处理作业,该作业采用CSV文件并将其写入HSQL嵌入式数据库。我的程序应该在CSV的每一行添加到DB时进行记录,但事实并非如此。我在运行时没有得到任何错误,但我知道作业没有被调用,因为它没有将任何内容记录到我的控制台中。

这是我的文件系统

这是我的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类

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 
}

这是我的Match.java模型类

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类

这个类应该在完成时记录主客场球队的名字。

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 Boot应用程序中的HSQL嵌入式数据库中。我已经按照官方的Spring Boot指南完成了Spring批处理作业(在这里:https://spring.io/guides/gs/batch-processing/),到目前为止还没有运气。

请尝试删除注释@EnableBatchProcessing

当您从jakarta命名空间导入时,我假设您正在使用Spring Boot 3和Spring Batch 5。

在Spring Boot 3中,Spring Batch注释@EnableBatchProcessing现在具有禁用Spring Batch自动配置的效果。如果您期望在应用程序启动时自动启动暴露的Job,那么您错过的就是这个自动配置。

请检查一下方法" afterjob ";正在做/发生其他状态作为BatchStatus。放弃了吗?

public void afterJob(JobExecution jobExecution) {
if (jobExecution.getStatus() == BatchStatus.ABANDONED) {
...

最新更新