I am creating a project for importing data from csv to MySQL using Spring batch using Spring 3.0.1. I created the configuration for Reader, Writer and Processor beans as follows along with step and job. The Older method using JobBuilderFactory and StepBuilderFactory is deprecated in Spring Boot 3.0
@Configuration
@EnableBatchProcessing
public class BatchConfig {
@Autowired
private PlayerRepository playerRepository;
@Bean
public FlatFileItemReader<Player> reader()
{
//Subclass of ItemReader class
FlatFileItemReader<Player> reader=new FlatFileItemReader<Player>();
reader.setResource(new ClassPathResource("People.csv"));
reader.setLineMapper(getLineMapper());
reader.setLinesToSkip(1);//Skip line in case of error
return reader;
}
private LineMapper<Player> getLineMapper() {
DefaultLineMapper<Player> lineMapper
=new DefaultLineMapper<Player>();
DelimitedLineTokenizer lineTokenizer=new DelimitedLineTokenizer();
lineTokenizer.setNames(new String[] {"playerID","birthYear","","","","","birthCity","","","","","","","nameFirst","nameLast","","","","","","","","retroID","bbrefID"});
lineTokenizer.setIncludedFields(new int[] {0,1,6,13,14,22,23});
BeanWrapperFieldSetMapper<Player> fieldSetMapper=new BeanWrapperFieldSetMapper<Player>();
fieldSetMapper.setTargetType(Player.class);
lineMapper.setLineTokenizer(lineTokenizer);
lineMapper.setFieldSetMapper(fieldSetMapper);
return lineMapper;
}
@Bean
public PlayerItemProcessor processor()
{
return new PlayerItemProcessor();
}
@Bean
public ItemWriter<Player> writer()
{
return player-> {
playerRepository.saveAll(player);
};
}
@Bean
public Job importPlayerJob(JobRepository jobRepository,Step step1)
{
return new JobBuilder("PLAYER-IMPORT-JOB",jobRepository).incrementer(new RunIdIncrementer()).flow(step1).end().build();//Write .start() if there is only one step
}
@Bean
public Step step1(JobRepository jobRepository,JpaTransactionManager jpaTransactionManager) {
return new StepBuilder("step1",jobRepository).<Player,Player>chunk(10,jpaTransactionManager).reader(reader()).processor(processor()).writer(writer()).build();
}
}
The PlayerItemProcessor is as follows:
package com.aryan.batch.config;
import org.springframework.batch.item.ItemProcessor;
import com.aryan.batch.modal.Player;
public class PlayerItemProcessor implements ItemProcessor<Player, Player> //Input and Output
{
@Override
public Player process(Player player) throws Exception {
return player;
}
}
Player Model is:
package com.aryan.batch.modal;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
public class Player {
@Id
private String playerId;
int birthYear;
String birthCity;
String nameFirst;
String nameLast;
String retroID;
String bbrefID;
}
PlayerRepository:
import org.springframework.data.jpa.repository.JpaRepository;
import com.aryan.batch.modal.Player;
public interface PlayerRepository extends JpaRepository<Player, String> {
}
The configuration in application.yml is:
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/batchdemo
username: hbstudent
password: hbstudent
batch:
jdbc:
initialize-schema: always
jpa:
show-sql: true
hibernate:
ddl-auto: update
When I run the project, the table is created successfully, but data is not inserted in the table. There are no errors indicating any kind of problem with the code.
CodePudding user response:
With Spring Boot 3, you don't need @EnableBatchProcessing
, unless you want to take complete control on how Spring Batch is configured and executed. So if you remove that annotation, your job should be executed on startup.
On another note, you are using a PlayerRepository
, which I guess is a JPA repository. If it is the case, make sure the transaction manager used in your step is a JpaTransactionManager
. The reason you are not seeing data being persisted is probably related to the fact that Spring Boot auto-configures a DataSourceTransactionManager
for the DataSource
you provided.
//How to specify name ?
Regarding this question in the definition of the importPlayerJob
job bean: you have already specified the name in the JobBuilder
bean definition in CsvToMySqlApplication
class. That said, I see no need to define the JobBuilder
and StepBuilder
as beans.