- Published on
Introdução ao Spring Batch: Da Teoria à Implementação de um Job Simples
- Authors
- Name
- Clayton Pereira
O Spring Batch é uma poderosa estrutura de processamento de lotes (batch processing) que permite a execução eficiente e escalável de tarefas de grande volume de dados. Se você está lidando com processos que envolvem a manipulação de grandes quantidades de dados, como migrações de banco de dados, geração de relatórios, ou processamento de transações, o Spring Batch pode ser uma solução ideal. Neste post, vamos explorar a teoria por trás do Spring Batch e, em seguida, criar um exemplo prático de um job simples.
O que é Spring Batch?
O Spring Batch é um framework de código aberto da Spring, projetado para gerenciar o processamento de grandes volumes de dados de forma eficiente. Ele oferece uma série de funcionalidades essenciais, como:
Gerenciamento de Jobs: Permite definir, executar e monitorar jobs de forma robusta. Step Processing: Divide o trabalho em steps, onde cada step pode ter leitura, processamento e gravação de dados. Retry e Skip: Oferece suporte a tentativas de reprocessamento e ignorar registros problemáticos. Transações: Suporte integrado a transações, garantindo a consistência dos dados. Escalabilidade: Pode ser configurado para rodar em múltiplos nós, distribuindo o processamento. Estrutura Básica de um Job no Spring Batch Um job no Spring Batch é composto por diversos componentes principais:
Job: A unidade principal de trabalho, que é composta por steps. Step: Cada step realiza uma tarefa específica e é composto por leitura, processamento e escrita. ItemReader: Responsável por ler os dados de uma fonte de entrada. ItemProcessor: Processa os dados lidos. ItemWriter: Escreve os dados processados em uma saída. Implementação de um Job Simples Vamos implementar um job simples que lê dados de um arquivo CSV, processa-os e grava os resultados em um banco de dados.
Dependências
Primeiro, adicione as dependências do Spring Batch e do banco de dados no seu arquivo pom.xml (para projetos Maven):
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-batch</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.batch</groupId> <artifactId>spring-batch-core</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </dependency></dependencies>
Configuração do Job
Crie uma classe de configuração para definir o job e os steps:
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.configuration.annotation.JobBuilderFactory;import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;import org.springframework.batch.core.launch.support.RunIdIncrementer;import org.springframework.batch.core.repository.JobRepository;import org.springframework.batch.item.ItemProcessor;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.batch.item.file.transform.DelimitedLineTokenizer;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.core.io.ClassPathResource;import org.springframework.jdbc.core.JdbcTemplate;import javax.sql.DataSource;
@Configuration@EnableBatchProcessingpublic class BatchConfiguration {
@Bean public FlatFileItemReader<Person> reader() { return new FlatFileItemReaderBuilder<Person>() .name("personItemReader") .resource(new ClassPathResource("sample-data.csv")) .delimited() .names(new String[]{"firstName", "lastName"}) .fieldSetMapper(new BeanWrapperFieldSetMapper<Person>() {{ setTargetType(Person.class); }}) .build(); }
@Bean public ItemProcessor<Person, Person> processor() { return person -> { person.setFirstName(person.getFirstName().toUpperCase()); person.setLastName(person.getLastName().toUpperCase()); return person; }; }
@Bean public JdbcBatchItemWriter<Person> writer(DataSource dataSource) { return new JdbcBatchItemWriterBuilder<Person>() .itemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>()) .sql("INSERT INTO people (first_name, last_name) VALUES (:firstName, :lastName)") .dataSource(dataSource) .build(); }
@Bean public Job importUserJob(JobBuilderFactory jobBuilderFactory, StepBuilderFactory stepBuilderFactory, DataSource dataSource) { Step step = stepBuilderFactory.get("step1") .<Person, Person> chunk(10) .reader(reader()) .processor(processor()) .writer(writer(dataSource)) .build();
return jobBuilderFactory.get("importUserJob") .incrementer(new RunIdIncrementer()) .start(step) .build(); }}
Classe Person
Crie uma classe Person que representa os dados lidos e processados:
public class Person { private String firstName; private String lastName;
// getters e setters}
Application
Por fim, configure a aplicação Spring Boot para iniciar o job:
import org.springframework.batch.core.launch.JobLauncher;import org.springframework.batch.core.launch.JobLauncher;import org.springframework.batch.core.launch.support.RunIdIncrementer;import org.springframework.batch.core.repository.JobRepository;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.CommandLineRunner;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplicationpublic class BatchApplication implements CommandLineRunner {
@Autowired JobLauncher jobLauncher;
@Autowired Job importUserJob;
public static void main(String[] args) { SpringApplication.run(BatchApplication.class, args); }
@Override public void run(String... args) throws Exception { jobLauncher.run(importUserJob, new JobParametersBuilder() .addLong("time", System.currentTimeMillis()).toJobParameters()); }}
Conclusão
O Spring Batch oferece uma estrutura robusta para o processamento de grandes volumes de dados, permitindo que você defina, execute e monitore jobs de forma eficiente. Com este exemplo simples, você pode começar a explorar as capacidades do Spring Batch e adaptar a solução às suas necessidades específicas de processamento de dados. O próximo passo pode incluir a implementação de técnicas avançadas, como particionamento e paralelização, para escalar seus jobs ainda mais.