Komplet guide til Spring Boot 4 · Lektion

Chunk-orienterede reader-processor-writer-flows

Forbind ItemReader-, ItemProcessor- og ItemWriter-komponenter til skalerbar chunk-behandling.

Lektion 2 af 413 trin

Chunk-orienterede reader-processor-writer-flows er en gratis Komplet guide til Spring Boot 4-lektion på CoddyKit. Dette er lektion 2 af 4. Du kan læse alle 3 lektioner i dette læringsspor gratis i deres fulde længde — derefter låser CoddyKit PRO alle lektioner op samt praktiske øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Den er en del af læringsforløbet i Komplet guide til Spring Boot 4, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Komplet guide til Spring Boot 4-kurset indeholder 4 lektioner i alt.

Hvorfor chunk-orienteret behandling?

Spring Batch læser, behandler og skriver data i chunks i stedet for én post ad gangen. En chunk er et konfigurerbart antal elementer (commit-interval), som håndteres i én enkelt transaktion.

  • Læs N elementer ét ad gangen med en ItemReader.
  • Behandl hvert element med en ItemProcessor.
  • Skriv hele samlingen på N på én gang med en ItemWriter.

Det er masseskrivning og bekræftelse pr. chunk, der får batchjob til at skalere til millioner af rækker uden at opbruge hukommelsen.

De tre centrale grænseflader

Hvert chunk-trin er bygget af tre grænseflader med én metode hver. At kende deres kontrakter er grundlaget for hele mønsteret.

  • ItemReader<I> → I read() returnerer det næste element eller null, når inddataene er opbrugt.
  • ItemProcessor<I, O> → O process(I item) omdanner inddata til uddata; hvis der returneres null, filtreres elementet fra.
  • ItemWriter<O> → void write(Chunk<? extends O> chunk) gemmer den opsamlede chunk.
public interface ItemReader<I> {
    I read() throws Exception; // null = end of input
}

public interface ItemProcessor<I, O> {
    O process(I item) throws Exception; // null = filter
}

public interface ItemWriter<O> {
    void write(Chunk<? extends O> chunk) throws Exception;
}

Definition af en domænetype

Et chunk-trin fører typede data fra læseren til processoren og videre til skriveren. Lad os modellere en enkel inddata- og uddataform. Læseren udsender rå Customer-poster, og skriveren gemmer normaliserede poster.

Ved at bruge en Java-record kan disse uforanderlige værdityper holdes korte. Dette kodestykke er ren Java uden framework, så det kan køres selvstændigt.

public class DomainDemo {
    record Customer(String name, String email) {}

    public static void main(String[] args) {
        Customer c = new Customer("  Ada ", "ADA@MAIL.COM");
        Customer normalized = new Customer(
                c.name().trim(),
                c.email().toLowerCase());
        System.out.println(normalized);
    }
}

Opbygning af ItemReader

Til databaseinddata streamer JdbcCursorItemReader rækker én ad gangen, så hukommelsesforbruget forbliver konstant. Du giver den en DataSource, en SQL-forespørgsel og en RowMapper, der omdanner hver række til et domæneobjekt.

Spring Batch kalder read() gentagne gange, indtil den returnerer null, og flytter markøren frem hver gang.

@Bean
public JdbcCursorItemReader<Customer> reader(DataSource dataSource) {
    return new JdbcCursorItemReaderBuilder<Customer>()
            .name("customerReader")
            .dataSource(dataSource)
            .sql("SELECT name, email FROM customers WHERE active = true")
            .rowMapper((rs, rowNum) ->
                    new Customer(rs.getString("name"), rs.getString("email")))
            .build();
}

Opbygning af ItemProcessor

Det er i processoren, forretningslogikken hører hjemme: validering, berigelse, omdannelse eller filtrering. Dens inddata- og uddatatyper kan være forskellige.

  • Returnér et omdannet objekt for at sende det videre i forløbet.
  • Returnér null for at springe elementet helt over — det når aldrig frem til skriveren.

Hold processorer uden tilstand og idempotente, så de fungerer korrekt, når chunks forsøges igen.

@Bean
public ItemProcessor<Customer, Customer> processor() {
    return customer -> {
        if (customer.email() == null || !customer.email().contains("@")) {
            return null; // filter invalid records out of the chunk
        }
        return new Customer(
                customer.name().trim(),
                customer.email().toLowerCase());
    };
}

Opbygning af ItemWriter

Skriveren modtager hele den behandlede chunk på én gang via en Chunk<O>. Massetskrivning — én samlet INSERT pr. chunk i stedet for én pr. række — er den vigtigste ydelsesforbedring.

JdbcBatchItemWriter bruger en parametriseret SQL-sætning og en parameterkilde baseret på bean-egenskaber til automatisk at knytte felter.

@Bean
public JdbcBatchItemWriter<Customer> writer(DataSource dataSource) {
    return new JdbcBatchItemWriterBuilder<Customer>()
            .dataSource(dataSource)
            .sql("INSERT INTO customers_clean (name, email) VALUES (:name, :email)")
            .beanMapped()
            .build();
}

Sammenkobling af chunk-trinnet

Et Step binder de tre komponenter sammen. De generiske typer <Customer, Customer> angiver chunkens ind- og uddata, og heltallet er bekræftelsesintervallet.

Med en chunkstørrelse på 100 læser Spring Batch 100 elementer, behandler hvert af dem og skriver derefter alle de resterende i én transaktion, før den bekræftes.

@Bean
public Step chunkStep(JobRepository jobRepository,
                      PlatformTransactionManager txManager,
                      ItemReader<Customer> reader,
                      ItemProcessor<Customer, Customer> processor,
                      ItemWriter<Customer> writer) {
    return new StepBuilder("chunkStep", jobRepository)
            .<Customer, Customer>chunk(100, txManager)
            .reader(reader)
            .processor(processor)
            .writer(writer)
            .build();
}

Sammensætning af jobbet

Et Job er et ordnet sæt af trin. For et enkelt chunk-trin starter jobbet blot med dette trin. Spring Boot registrerer automatisk Job-beanen og kører den ved opstart.

JobRepository registrerer kørselsmetadata — status, antal læste/skrevne elementer og den senest bekræftede position — hvilket muliggør genstart.

@Bean
public Job importCustomersJob(JobRepository jobRepository, Step chunkStep) {
    return new JobBuilder("importCustomersJob", jobRepository)
            .start(chunkStep)
            .build();
}

Valg af chunkstørrelse

Bekræftelsesintervallet er en justeringsmulighed, ikke et magisk tal.

  • For lille (f.eks. 1): én transaktion pr. række — stort bekræftelsesoverhead og langsom kørsel.
  • For stort (f.eks. 100.000): større transaktioner, mere hukommelse og større omkostning ved tilbageførsel, hvis en chunk mislykkes.
  • Typisk godt udgangspunkt: 100–1000, justeret ved at måle gennemløbet i forhold til din database og række størrelse.

Husk: Et mislykket element tilbagefører hele chunken, så større chunks betyder mere arbejde, der skal udføres igen ved fejl.

Fejltolerance: Spring over og prøv igen

Virkelige inddata er ofte uensartede. Pak trinnet ind i .faultTolerant() for at fortsætte behandlingen trods isolerede fejl.

  • .skip(...) — tolerér op til skipLimit ugyldige elementer i stedet for at lade jobbet mislykkes.
  • .retry(...) — prøv igen ved midlertidige fejl (f.eks. deadlocks) op til retryLimit, før forsøget opgives.

Ved et spring over eller et nyt forsøg gennemgår Spring Batch chunken igen element for element for at isolere den problematiske post.

@Bean
public Step faultTolerantStep(JobRepository jobRepository,
                              PlatformTransactionManager txManager,
                              ItemReader<Customer> reader,
                              ItemProcessor<Customer, Customer> processor,
                              ItemWriter<Customer> writer) {
    return new StepBuilder("ftStep", jobRepository)
            .<Customer, Customer>chunk(100, txManager)
            .reader(reader)
            .processor(processor)
            .writer(writer)
            .faultTolerant()
            .skip(FlatFileParseException.class)
            .skipLimit(20)
            .retry(DeadlockLoserDataAccessException.class)
            .retryLimit(3)
            .build();
}

Chunkens livscyklus i rækkefølge

Samlet set følger hver chunk den samme løkke i én transaktion:

  • 1. Læs: kald read() gentagne gange, indtil der er lagt et antal elementer svarende til chunkstørrelsen i buffer (eller null afslutter inddataene).
  • 2. Behandl: kald process() på hvert element; null-værdier filtreres fra.
  • 3. Skriv: send de resterende elementer som én Chunk til write().
  • 4. Bekræft: bekræft transaktionen, og registrer fremdriften i JobRepository.

Derefter gentages løkken for den næste chunk, indtil læseren er tømt.

Hurtigt tjek

Afprøv din forståelse af chunk-forløbet.

Opsummering

Du har koblet et komplet chunk-orienteret forløb sammen i Spring Batch:

  • ItemReader streamer inddata ét element ad gangen og returnerer null ved slutningen.
  • ItemProcessor omdanner eller filtrerer elementer; null fjerner et element.
  • ItemWriter gemmer hele chunken samlet for at opnå bedre ydeevne.
  • Step binder dem sammen med et chunk(size, txManager)-bekræftelsesinterval, og Job koordinerer trinnene.
  • Juster chunkstørrelsen efter gennemløbet, og tilføj .faultTolerant() med spring over/forsøg igen for robuste behandlingsforløb.

Denne læs-behandl-skriv-løkke, der bekræftes pr. chunk, er rygraden i skalerbar batchbehandling.

Gratis at komme i gang

Lær Java med en AI-underviser — gratis

Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.

Kurser
21
Lektioner
84

Ofte stillede spørgsmål

Er lektionen “Chunk-orienterede reader-processor-writer-flows” gratis?

Ja — alle 3 lektioner i læringssporet Komplet guide til Spring Boot 4, inklusive “Chunk-orienterede reader-processor-writer-flows”, kan læses gratis i deres fulde længde her på webstedet. Derefter låser CoddyKit PRO alle lektioner op samt interaktive øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Komplet guide til Spring Boot 4-kurset indeholder 4 lektioner i alt.

Hvad lærer jeg i “Chunk-orienterede reader-processor-writer-flows”?

Forbind ItemReader-, ItemProcessor- og ItemWriter-komponenter til skalerbar chunk-behandling. Du øver dig i Komplet guide til Spring Boot 4 med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.

Skal jeg have erfaring for at begynde på Komplet guide til Spring Boot 4?

Der kræves ingen tidligere erfaring. Komplet guide til Spring Boot 4 på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 2 af 4.

Hvor lang tid tager lektionen “Chunk-orienterede reader-processor-writer-flows”?

De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.

Kan jeg skrive og køre kode i denne Komplet guide til Spring Boot 4-lektion?

Ja. Alle Komplet guide til Spring Boot 4-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.

Alle lektioner i dette kursus

  1. Jobs, steps og JobRepository-modellen
  2. Chunk-orienterede reader-processor-writer-flows
  3. Fault tolerance, skip- og retry-politikker
  4. Partitionering og parallel step-eksekvering
← Tilbage til Komplet guide til Spring Boot 4