Open In App

Spring Boot Batch Processing Using Spring Data JPA to CSV File

The Spring Batch is a framework in the Spring Boot ecosystem It can provide a lot of functionalities for Batch processing. The Spring Batch framework simplifies the batch development of applications by providing reliable components and other patterns for common batch processing concerns.

Mostly, batch processing is used to read and write data in bulk amounts of data, This Batch processing can be able to handle transactions of data and process the data in the form of chunks, and the other one manages the job execution also.



In this article, we will learn the required terminology of Spring Batch processing using Spring Data JPA to CSV File.

Key Terminologies:

Required Tools and Technologies

Below, the tools and Technologies we have used for this Spring Boot Batch Processing using Spring Data JPA to CSV File and also, we need to know How to create a Spring Boot Project with STS.



Project Structure:

This structure is only for learning purpose but in real time The Folder Structure is dependents on the Project. And we can observe there is no CSV File in that Folder Structure.

Add dependencies

Below we have provided the required dependencies for this project. Every dependency is used for unique purpose. For your reference the dependencies listed below.

dependencies {
implementation 'org.springframework.boot:spring-boot-starter-batch'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'mysql:mysql-connector-java:8.0.23'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.batch:spring-batch-test'
}

Note: We have already some data in the table.

Below we have the books table which has some data inside it.

Main Class

In this class, we have used this annotation @EnableBatchProcessing. This Annotation is used for Batch related functionality in the Spring Boot. Then only we can call different functions belongs to Batch Processing.




package com.batch.app;
  
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
  
@SpringBootApplication
@EnableBatchProcessing
public class BatchApplication {
  
    public static void main(String[] args)
    {
        SpringApplication.run(BatchApplication.class, args);
    }
}

Book Entity Class

Now, we will create one Entity class in the project Folder named as Book.

Below we have provided that code for better understanding.




package com.batch.app;
  
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
  
@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "book")
public class Book {
  
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    private String author;
    private String name;
    private String price;
}

BookEntityRepository

Here, we have created one interface named BookEntityRepository which is extends to JpaRepository.




package com.batch.app;
  
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.stereotype.Repository;
  
@Repository
@EnableJpaRepositories
public interface BookEntityRepository
    extends JpaRepository<Book, Integer> {
}

BookEntityItemProcessor

Now, we will create one class that is BookEntityItemProcessor which is used for processing the data based the business logic.




package com.batch.app;
  
import org.springframework.batch.item.ItemProcessor;
import org.springframework.stereotype.Component;
  
@Component
public class BookEntityItemProcessor
    implements ItemProcessor<Book, Book> {
  
    @Override
    public Book process(Book item) throws Exception
    {
        return item;
    }
}

BookEntityCsvWriter

Here, we have created one more Java class with named BookEntityCsvWriter for Handling getting the processed data and write into CSV file.




package com.batch.app;
  
import java.io.File;
import java.util.List;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.file.FlatFileItemWriter;
import org.springframework.batch.item.file.transform.BeanWrapperFieldExtractor;
import org.springframework.batch.item.file.transform.DelimitedLineAggregator;
import org.springframework.core.io.FileSystemResource;
  
public class BookEntityCsvWriter
    implements ItemWriter<Book> {
    private static final String CSV_FILE = "output.csv";
    private FlatFileItemWriter<Book> writer;
  
    public BookEntityCsvWriter()
    {
        initializeCsvFile();
        this.writer = new FlatFileItemWriter<>();
        this.writer.setResource(
            new FileSystemResource(CSV_FILE));
        this.writer.setLineAggregator(
            new DelimitedLineAggregator<Book>() {
                {
                    setDelimiter(",");
                    setFieldExtractor(
                        new BeanWrapperFieldExtractor<
                            Book>() {
                            {
                                setNames(new String[] {
                                    "id", "author", "name",
                                    "price" });
                            }
                        });
                }
            });
    }
  
    private void initializeCsvFile()
    {
        File file = new File(CSV_FILE);
        if (!file.exists()) {
            try {
                file.createNewFile();
            }
            catch (Exception e) {
                throw new RuntimeException(
                    "Error creating CSV file", e);
            }
        }
    }
  
    public void write(List<? extends Book> items)
        throws Exception
    {
  
        writer.write(items);
    }
}

Batch Configuration

This is the required Java logic for handling entire Batch processing logic.




package com.batch.app;
  
import java.util.Properties;
import javax.persistence.EntityManagerFactory;
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.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.database.JpaPagingItemReader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
  
@Configuration
@EnableBatchProcessing
public class BatchConfiguration {
  
    @Autowired private JobBuilderFactory jobBuilderFactory;
  
    @Autowired
    private StepBuilderFactory stepBuilderFactory;
  
    @Bean
    public ItemReader<Book>
    reader(EntityManagerFactory entityManagerFactory)
    {
        JpaPagingItemReader<Book> reader
            = new JpaPagingItemReader<>();
        reader.setEntityManagerFactory(
            entityManagerFactory);
        reader.setQueryString(
            "SELECT b FROM Book b"); // Use the entity name
                                     // 'Book'
        reader.setPageSize(10);
        return reader;
    }
  
    @Bean public ItemProcessor<Book, Book> processor()
    {
        return new BookEntityItemProcessor();
    }
  
    @Bean public ItemWriter<Book> writer()
    {
        return new BookEntityCsvWriter();
    }
  
    @Bean public Job exportJob(Step exportStep)
    {
        return jobBuilderFactory.get("exportJob")
            .incrementer(new RunIdIncrementer())
            .flow(exportStep)
            .end()
            .build();
    }
  
    @Bean
    public Step
    exportStep(ItemReader<Book> reader,
               ItemProcessor<Book, Book> processor,
               ItemWriter<Book> writer)
    {
        return stepBuilderFactory.get("exportStep")
            .<Book, Book>chunk(10)
            .reader(reader)
            .processor(processor)
            .writer(writer)
            .build();
    }
  
    @Bean public EntityManagerFactory entityManagerFactory()
    {
        LocalContainerEntityManagerFactoryBean emf
            = new LocalContainerEntityManagerFactoryBean();
        emf.setDataSource(dataSource());
        emf.setPackagesToScan("com.batch.app");
        emf.setJpaVendorAdapter(
            new HibernateJpaVendorAdapter());
        emf.setJpaProperties(jpaProperties());
        emf.afterPropertiesSet();
        return emf.getObject();
    }
  
    @Bean public DataSource dataSource()
    {
        DriverManagerDataSource dataSource
            = new DriverManagerDataSource();
        dataSource.setDriverClassName(
            "com.mysql.cj.jdbc.Driver");
        dataSource.setUrl(
            "jdbc:mysql://localhost:3306/books");
        dataSource.setUsername("root");
        dataSource.setPassword("password");
        return dataSource;
    }
  
    @Bean public Properties jpaProperties()
    {
        Properties properties = new Properties();
        properties.setProperty(
            "hibernate.dialect",
            "org.hibernate.dialect.MySQLDialect");
        return properties;
    }
}

Output:

After running this project as Spring Boot Application, one CSV file is created. Then it will fetch data from database then write that data into that CSV File. Below we have provided the CSV file output.

CSV File Output:


Article Tags :