[JAVA] [Spring Batch] Données de la table de sortie dans un fichier CSV

introduction

J'ai essayé le traitement par lots à l'aide de tasklet. J'utilise également les curseurs MyBatis pour gérer le chargement en masse des tables.

Créer un projet

Créez un projet à l'aide de Spring Initializr. Dans Dépendances, sélectionnez Batch, Lombok, MyBatis et le pilote DBC pour votre base de données (mon article utilise MySQL).

fichier de configuration

application.properties


#Niveau de journal
logging.level.com.sample.demo=debug

#Informations de connexion à la base de données
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/demo?characterEncoding=UTF-8&serverTimezone=JST&sslMode=DISABLED
spring.datasource.username=hoge
spring.datasource.password=hoge

#Extraire la taille
#mybatis.configuration-properties.default-fetch-size=10000
mybatis.configuration-properties.fetch-size=10000

#Taille d'écriture du fichier
demo.write-size=1000

La source

Lisez le DB et sortez le fichier.

DemoTasklet.java


package com.sample.demo;

import java.util.ArrayList;
import java.util.List;

import org.apache.ibatis.cursor.Cursor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.item.ItemStreamWriter;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component()
public class DemoTasklet implements Tasklet {
	private Logger logger = LoggerFactory.getLogger(DemoTasklet.class);

	@Autowired
	private DemoRepository demoRepository;

	@Autowired
	private ItemStreamWriter<DemoDTO> writer;

	@Autowired
	private DemoContext demoContext;

	public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) throws Exception {
		logger.debug("DemoTasklet exécute démarrer");

		writer.open(chunkContext.getStepContext().getStepExecution().getExecutionContext());
		try(Cursor<DemoDTO> result = demoRepository.select()) {
			List<DemoDTO> data = new ArrayList<>();
			for(DemoDTO dto: result) {
				data.add(dto);
				if (data.size() >= demoContext.getWriteSize()) {
					writer.write(data);
					data.clear();
				}
			}
			if (data.size() > 0) writer.write(data);
		}
		writer.close();

		logger.debug("Exécution de DemoTasklet terminée");
		return RepeatStatus.FINISHED;
	}

}

Enregistrez le Tasklet et définissez le fichier CSV.

BatchConfig.java


package com.sample.demo;

import java.io.IOException;
import java.io.Writer;

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.file.FlatFileHeaderCallback;
import org.springframework.batch.item.file.FlatFileItemWriter;
import org.springframework.batch.item.file.transform.BeanWrapperFieldExtractor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;

@Configuration
@EnableBatchProcessing
public class BatchConfig {
	@Autowired
    private JobBuilderFactory jobBuilderFactory;

    @Autowired
    private StepBuilderFactory stepBuilderFactory;

    @Autowired
    private DemoTasklet demoTasklet;

    private Resource outputResource = new FileSystemResource("output/data.csv");

    @Bean
    public DemoContext createDemoContext() {
    	return new DemoContext();
    }

	@Bean
	public FlatFileItemWriter<DemoDTO> writer()
	{
		FlatFileItemWriter<DemoDTO> writer = new FlatFileItemWriter<>();
		writer.setResource(outputResource);
		writer.setEncoding("UTF-8");
		writer.setLineSeparator("\r\n");
		writer.setAppendAllowed(false);

		writer.setHeaderCallback(new FlatFileHeaderCallback() {
			public void writeHeader(Writer arg0) throws IOException {
				arg0.append("\"ID\",\"Nom\",\"adresse mail\"");
			}
		});

		writer.setLineAggregator(new CsvLineAggregator<DemoDTO>() {
			{
				setFieldExtractor(new BeanWrapperFieldExtractor<DemoDTO>() {
					{
						setNames(new String[] { "id", "name", "mailAddress" });
					}
				});
			}
		});

		return writer;
    }

	@Bean
	public Step step1() {
		return stepBuilderFactory.get("step1").tasklet(demoTasklet).build();
	}

	@Bean
	public Job job(Step step1) {
		return jobBuilderFactory.get("job").incrementer(new RunIdIncrementer()).start(step1).build();
	}
}

La valeur-clé définie dans [demo.] Dans application.properties est définie.

DemoContext.java


package com.sample.demo;

import org.springframework.boot.context.properties.ConfigurationProperties;

import lombok.Data;

@ConfigurationProperties(prefix="demo")
@Data
public class DemoContext {
	private int writeSize;
}

Si vous utilisez la classe préparée par spring, vous ne pouvez pas définir le caractère de la boîte, donc si vous voulez définir le caractère de la boîte, vous devez créer le vôtre.

CsvLineAggregator.java


package com.sample.demo;

import java.util.Arrays;

import org.springframework.batch.item.file.transform.ExtractorLineAggregator;
import org.springframework.util.StringUtils;

public class CsvLineAggregator<T> extends ExtractorLineAggregator<T> {

	private String enclose = "\"";

	private String delimiter = ",";

	public void setEnclose(String enclose) {
		this.enclose = enclose;
	}

	public void setDelimiter(String delimiter) {
		this.delimiter = delimiter;
	}

	@Override
	protected String doAggregate(Object[] fields) {
		return StringUtils.collectionToDelimitedString(Arrays.asList(fields), this.delimiter, this.enclose, this.enclose);
	}

}

DTO

DemoDTO.java


package com.sample.demo;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Data
public class DemoDTO {
	private String id;
	private String name;
	private String mailAddress;
}

Interface pour SQL

DemoRepository.java


package com.sample.demo;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.cursor.Cursor;

@Mapper
public interface DemoRepository {

	Cursor<DemoDTO> select();

}

SQL

DemoRepository.xml


<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org/DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.sample.demo.DemoRepository">

    <select id="select" resultType="com.sample.demo.DemoDTO" fetchSize="${fetch-size}">
      SELECT
        id,
        name,
        mail_address as mailAddress
      FROM
        users
    </select>
</mapper>

Recommended Posts

[Spring Batch] Données de la table de sortie dans un fichier CSV
Flux jusqu'à la sortie des données de la table à afficher avec Spring Boot
Sortie de fichier csv avec csv ouvert
Sortie javaDoc dans un fichier Word
Sortie de l'arborescence XML dans un fichier
Remarques sur l'utilisation de Spring Data JDBC
[Comment installer Spring Data Jpa]
Enregistrer la sortie dans un fichier en Java
Sortie du journal Spring Data JPA SQL
J'ai créé un outil pour afficher la différence du fichier CSV
Fichier de migration pour ajouter un commentaire à la table Rails
Pour écrire des données de réponse directement dans Spring
Ruby: CSV :: Comment utiliser la note de tableau
Comment diviser un fichier de message Spring Boot
Bean de sortie au format JSON au printemps
Exemple de traitement par lots de données sur DB avec des démarreurs Apache Camel Spring Boot
[Ruby] Comment convertir un fichier CSV en Yaml (Yml)
Comment sortir le CSV créé par Rails vers S3
Le navigateur Spring Data REST HAL confirme l'opération Spring REST
Introduction à Spring Boot + In-Memory Data Grid
J'ai essayé de sortir quatre-vingt-dix-neuf en Java
Comment se lier avec un fichier de propriétés dans Spring Boot
[Spring Boot] Comment se référer au fichier de propriétés
J'ai essayé d'implémenter le téléchargement de fichiers avec Spring MVC
J'ai essayé de lire et de sortir CSV avec Outsystems
Journal de sortie vers un fichier externe avec slf4j + logback avec Maven
J'ai essayé de démarrer avec Spring Data JPA
[Java] [Spring] [Spring Batch] Ne pas créer / utiliser la table de métadonnées Spring Batch
Convertir un fichier csv en fichier d'enregistrement de longueur fixe à l'aide d'énumération
Comment tester l'écran de téléchargement de fichiers avec Spring + Selenium
Comment utiliser le référentiel de jobs en mémoire avec Spring Batch