Logo do Site
Published on

Introdução ao Spring Batch: Da Teoria à Implementação de um Job Simples

Authors
  • avatar
    Name
    Clayton Pereira
    Twitter

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
@EnableBatchProcessing
public 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;
@SpringBootApplication
public 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.