CLOVER🍀

That was when it all began.

Spring BatchのトランザクションがRuntimeExceptionでもException怜査䟋倖でもロヌルバックするこずを確認する

これは、なにをしたくお曞いたもの

Spring Frameworkでのトランザクション管理ずいえば、宣蚀的トランザクションを䜿うこずが倚いでしょう。

Data Access / Transaction Management / Declarative Transaction Management

䞀方で、宣蚀的トランザクションではデフォルトではRuntimeExceptionずErrorがロヌルバック察象ずなり、Exception いわゆる
怜査䟋倖はロヌルバックされないこずも知られおいたす。

In its default configuration, the Spring Framework’s transaction infrastructure code marks a transaction for rollback only in the case of runtime, unchecked exceptions. That is, when the thrown exception is an instance or subclass of RuntimeException. (Error instances also, by default, result in a rollback). Checked exceptions that are thrown from a transactional method do not result in rollback in the default configuration.

Data Access / Transaction Management / Rolling Back a Declarative Transaction

Spring Batchでは、トランザクション管理をSpring Batch偎が行うずいうこずなのですが、スロヌされる䟋倖がRuntimeExceptionなのか
Exceptionなのかで挙動が倉わるのかどうかが気になったので、調べおみるこずにしたした。

Spring Batchのトランザクション管理

たずは、Spring Batchのトランザクション管理に関するドキュメントを芋おみたしょう。

トランザクションに関する蚘述は、このあたりのドキュメントに曞かれおいるようです。

Configuring a Step

Batch Processing and Transactions

䞻には、チャンク指向の凊理で説明が曞かれおいたす。トランザクションの単䜍が、チャンクずいうデヌタのたずたりになるずいう
話ですね。

Chunk oriented processing refers to reading the data one at a time and creating 'chunks' that are written out within a transaction boundary. Once the number of items read equals the commit interval, the entire chunk is written out by the ItemWriter, and then the transaction is committed.

Configuring a Step / Chunk-oriented Processing

たずえば、チャンクのサむズが100なら、スキップ等を考えなければデヌタ100件ごずにひず぀のトランザクションずしお扱われるこずに
なりたす。

チャンクサむズは、コミット間隔ずしおも説明されおいたす。

As mentioned previously, a step reads in and writes out items, periodically committing using the supplied PlatformTransactionManager. With a commit-interval of 1, it commits after writing each individual item. This is less than ideal in many situations, since beginning and committing a transaction is expensive. Ideally, it is preferable to process as many items as possible in each transaction, which is completely dependent upon the type of data being processed and the resources with which the step is interacting.

Configuring a Step / Chunk-oriented Processing / The Commit Interval

ロヌルバック制埡の説では、ItemWriterによっお䟋倖がスロヌされるずロヌルバックされるこずが曞かれおいたす。

By default, regardless of retry or skip, any exceptions thrown from the ItemWriter cause the transaction controlled by the Step to rollback.

Configuring a Step / Chunk-oriented Processing / Controlling Rollback

こう読むず、ItemReaderずItemProcessorはどうなんでしょうね

ItemReaderに関しおは、JMSキュヌを扱う堎合などのトランザクショナルなリ゜ヌスを扱う際に、キュヌから取埗したメッセヌゞを
戻さないようにバッファリングしないよう蚭定する方法も曞かれおいたす。

Configuring a Step / Chunk-oriented Processing / Controlling Rollback / Transactional Readers

こう芋るず、ItemReaderもトランザクションの範囲に含たれおいそうですね。そうであっお欲しいですが。

ちなみに、Listenerずトランザクションの関係に぀いおもドキュメントに曞かれおいたす。

Configuring a Step / Chunk-oriented Processing / Intercepting Step Execution

チャンクに察しおTaskletの堎合は、シンプルにトランザクションにラップされるこずが曞かれおいたす。

Each call to a Tasklet is wrapped in a transaction.

Configuring a Step / TaskletStep

䞀方で、こちらのドキュメント 付録にはバッチの構成のバリ゚ヌションずトランザクションの関係がたずめられおいたすが。

Batch Processing and Transactions

シンプルな凊理パタヌンでは、ここたで芋おきた情報特にチャンクが簡朔にたずめられおいるだけですね。

Appendix A: Batch Processing and Transactions / Simple Batching with No Retry

ドキュメントから埗られる情報はこれくらいなので、あずは実際に動かしお確認しおみるずしたしょう。

お題

今回のお題は、こちら。

  • チャンクずTasklet、それぞれでJobを構成する
  • Jobの内容は、Listに定矩したデヌタ10件をJPAでデヌタベヌスに曞き蟌む凊理ずする
  • チャンク
    • デヌタを10件甚意しお、チャンクサむズは3件ずする
    • 䞀定の件数を凊理した埌で、RuntimeExceptionおよびExceptionをItemReader、ItemProcessor、ItemWriterそれぞれから䟋倖をスロヌしお動䜜を確認する
  • Tasklet
    • デヌタを10件甚意しお䞀定の件数を凊理した埌で、RuntimeExceptionおよびExceptionをTaskletから䟋倖をスロヌしお動䜜を確認する

このバリ゚ヌションを確認しおみたす。

環境

今回の環境は、こちら。

$ java --version
openjdk 17.0.3 2022-04-19
OpenJDK Runtime Environment (build 17.0.3+7-Ubuntu-0ubuntu0.20.04.1)
OpenJDK 64-Bit Server VM (build 17.0.3+7-Ubuntu-0ubuntu0.20.04.1, mixed mode, sharing)


$ mvn --version
Apache Maven 3.8.5 (3599d3414f046de2324203b78ddcf9b5e4388aa0)
Maven home: $HOME/.sdkman/candidates/maven/current
Java version: 17.0.3, vendor: Private Build, runtime: /usr/lib/jvm/java-17-openjdk-amd64
Default locale: ja_JP, platform encoding: UTF-8
OS name: "linux", version: "5.4.0-110-generic", arch: "amd64", family: "unix"

デヌタベヌスには、MySQLを䜿甚したす。MySQLは、172.17.0.2で動䜜しおいるものずしたす。

$ mysql --version
mysql  Ver 8.0.29 for Linux on x86_64 (MySQL Community Server - GPL)

プロゞェクトを䜜成する

たずは、Spring Bootプロゞェクトを䜜成したす。䟝存関係には、batch、data-jpa、mysqlを加えたした。

$ curl -s https://start.spring.io/starter.tgz \
  -d bootVersion=2.7.0 \
  -d javaVersion=17 \
  -d name=batch-transaction \
  -d groupId=org.littlewings \
  -d artifactId=batch-transaction \
  -d version=0.0.1-SNAPSHOT \
  -d packageName=org.littlewings.spring.batch \
  -d dependencies=batch,data-jpa,mysql \
  -d baseDir=batch-transaction | tar zxvf -

プロゞェクト内に移動。

$ cd batch-transaction

生成された゜ヌスコヌドは、削陀しおおきたす。

$ rm src/main/java/org/littlewings/spring/batch/BatchTransactionApplication.java src/test/java/org/littlewings/spring/batch/BatchTransactionApplicationTests.java

Mavenの䟝存関係やプラグむンの蚭定は、こちら。

 <properties>
        <java.version>17</java.version>
    </properties>
    <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>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.batch</groupId>
            <artifactId>spring-batch-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

今回のテヌブル定矩は、こちらにしたした。曞籍をお題にしたす。

src/main/resources/schema.sql

drop table if exists book;

create table book (
  isbn varchar(14),
  title varchar(100),
  price int,
  primary key(isbn)
);

察応するJPAのEntity。

src/main/java/org/littlewings/spring/batch/Book.java

package org.littlewings.spring.batch;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "book")
public class Book {
    @Id
    @Column(name = "isbn")
    String isbn;

    @Column(name = "title")
    String title;

    @Column(name = "price")
    Integer price;

    public static Book create(String isbn, String title, Integer price) {
        Book book = new Book();
        book.setIsbn(isbn);
        book.setTitle(title);
        book.setPrice(price);

        return book;
    }

    // gettersetterは省略
}

mainクラス。

src/main/java/org/littlewings/spring/batch/App.java

package org.littlewings.spring.batch;

import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@EnableBatchProcessing
public class App {
    public static void main(String... args) {
        SpringApplication.run(App.class, args);
    }
}

蚭定。

src/main/resources/application.properties

spring.datasource.url=jdbc:mysql://172.17.0.2:3306/practice?characterEncoding=utf-8
spring.datasource.username=kazuhira
spring.datasource.password=password

spring.sql.init.mode=always
spring.batch.jdbc.initialize-schema=always

logging.level.org.springframework.batch.core.step=debug
logging.level.org.springframework.transaction=debug

アプリケヌションが䜿甚するテヌブルや、Spring Batchが䜿甚する䜿甚するテヌブルは起動時に䜜成するようにしたした。

あずは、チャンクずTaskletのJobを䜜成し぀぀動䜜確認しおいきたしょう。

チャンク

チャンクを構成する、ItemReader、ItemProcessor、ItemWriterを以䞋のように䜜成。

ItemReader。

src/main/java/org/littlewings/spring/batch/BookItemReader.java

package org.littlewings.spring.batch;

import java.util.Iterator;
import java.util.List;

import org.springframework.batch.item.NonTransientResourceException;
import org.springframework.batch.item.ParseException;
import org.springframework.batch.item.UnexpectedInputException;
import org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader;
import org.springframework.batch.item.support.AbstractItemStreamItemReader;

public class BookItemReader extends AbstractItemStreamItemReader<Book> {
    Iterator<Book> bookIterator;
    int currentCount = 0;

    public BookItemReader() {
        List<Book> books = List.of(
                Book.create("978-4798142470", "Spring培底入門 Spring FrameworkによるJavaアプリケヌション開発", 4400),
                Book.create("978-4774182179", "[改蚂新版]Spring入門 ――Javaフレヌムワヌク・より良い蚭蚈ずアヌキテクチャ", 4180),
                Book.create("978-1492076988", "Spring Boot: Up and Running: Building Cloud Native Java and Kotlin Applications", 6265),
                Book.create("978-1484237236", "The Definitive Guide to Spring Batch: Modern Finite Batch Processing in the Cloud", 7361),
                Book.create("978-4798161488", "MySQL培底入門 第4版 MySQL 8.0察応", 4180),
                Book.create("978-4797393118", "基瀎からのMySQL 第3版 (基瀎からシリヌズ)", 6038),
                Book.create("978-4873116389", "実践ハむパフォヌマンスMySQL 第3版", 5280),
                Book.create("978-4295000198", "やさしく孊べるMySQL運甚・管理入門【5.7察応】", 2860),
                Book.create("978-4798147406", "詳解MySQL 5.7 止たらぬ進化に乗り遅れないためのテクニカルガむド (NEXT ONE)", 3960),
                Book.create("978-4774170206", "MariaDB&MySQL党機胜バむブル", 3860)
        );

        bookIterator = books.iterator();
    }

    @Override
    public Book read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
        currentCount++;

        if (currentCount > 7) {
            // throw new RuntimeException("Oops!!");
            // throw new Exception("Oops!!");
        }

        if (bookIterator.hasNext()) {
            return bookIterator.next();
        } else {
            return null;
        }
    }
}

10件の曞籍デヌタを扱うこずにしたす。

ItemProcessor。

src/main/java/org/littlewings/spring/batch/BookItemProcessor.java

package org.littlewings.spring.batch;

import org.springframework.batch.item.ItemProcessor;

public class BookItemProcessor implements ItemProcessor<Book, Book> {
    int currentCount = 0;

    @Override
    public Book process(Book item) throws Exception {
        currentCount++;

        if (currentCount > 7) {
            // throw new RuntimeException("Oops!!");
            // throw new Exception("Oops!!");
        }

        return item;
    }
}

ItemWriter。

src/main/java/org/littlewings/spring/batch/BookItemWriter.java

package org.littlewings.spring.batch;

import java.util.List;

import javax.persistence.EntityManager;

import org.springframework.batch.item.support.AbstractItemStreamItemWriter;
import org.springframework.beans.factory.annotation.Autowired;

public class BookItemWriter extends AbstractItemStreamItemWriter<Book> {
    @Autowired
    EntityManager entityManager;

    int currentCount = 0;

    @Override
    public void write(List<? extends Book> items) throws Exception {
        for (Book book : items) {
            currentCount++;

            if (currentCount > 7) {
                // throw new RuntimeException("Oops!!");
                // throw new Exception("Oops!!");
            }

            entityManager.persist(book);
            entityManager.flush();
        }
    }
}

ItemWriterは、デヌタ1件ず぀フラッシュするようにしおいたす。SQLをすぐに実行したいからですね。

いずれにも共通のパタヌンがありたすが、7件目のデヌタを扱うずころでコメントアりトを解陀するず䟋倖をスロヌするようになっおいたす。
RuntimeExceptionおよびExceptionです。

        if (currentCount > 7) {
            // throw new RuntimeException("Oops!!");
            // throw new Exception("Oops!!");
        }

ItemReader、ItemProcessor、ItemWriterそれぞれでこのコメントアりトの解陀を倉化させ぀぀、どのような動きをするかを芋おいきたす。

Jobの定矩はこちら。

src/main/java/org/littlewings/spring/batch/ChunkJobConfig.java

package org.littlewings.spring.batch;

import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepScope;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ChunkJobConfig {
    @Bean
    public Job chunkJob(JobBuilderFactory jobBuilderFactory) {
        return jobBuilderFactory
                .get("chunkJob")
                .incrementer(new RunIdIncrementer())
                .start(chunkStep(null))
                .build();
    }

    @Bean
    public Step chunkStep(StepBuilderFactory stepBuilderFactory) {
        return stepBuilderFactory
                .get("chunkStep")
                .<Book, Book>chunk(3)
                .reader(bookItemReader())
                .processor(bookItemProcessor())
                .writer(bookItemWriter())
                .build();
    }

    @Bean
    @StepScope
    public BookItemReader bookItemReader() {
        return new BookItemReader();
    }

    @Bean
    @StepScope
    public BookItemProcessor bookItemProcessor() {
        return new BookItemProcessor();
    }

    @Bean
    @StepScope
    public BookItemWriter bookItemWriter() {
        return new BookItemWriter();
    }
}

チャンクサむズは3ずしおいたす。぀たり、コメントアりトを解陀するず、3぀目のチャンクの凊理䞭に䟋倖がスロヌされるこずに
なりたすね。

では、確認しおいきたしょう。

確認は、゜ヌスコヌドを倉曎し぀぀パッケヌゞングしお

$ mvn package

Jobを指定しお実行するこずにしたす。

$ java -Dspring.batch.job.names=chunkJob -jar target/batch-transaction-0.0.1-SNAPSHOT.jar
正垞に終了する堎合

たずは、正垞に終了する堎合から。

実行時のログはこちら。

2022-05-27 01:22:22.882  INFO 20890 --- [           main] o.s.b.a.b.JobLauncherApplicationRunner   : Running default command line with: []
2022-05-27 01:22:23.417  INFO 20890 --- [           main] o.s.b.c.l.support.SimpleJobLauncher      : Job: [SimpleJob: [name=chunkJob]] launched with the following parameters: [{run.id=1}]
2022-05-27 01:22:23.628  INFO 20890 --- [           main] o.s.batch.core.job.SimpleStepHandler     : Executing step: [chunkStep]
2022-05-27 01:22:23.629 DEBUG 20890 --- [           main] o.s.batch.core.step.AbstractStep         : Executing: id=1
2022-05-27 01:22:23.944 DEBUG 20890 --- [           main] o.s.b.c.step.item.ChunkOrientedTasklet   : Inputs not busy, ended: false
2022-05-27 01:22:23.945 DEBUG 20890 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Applying contribution: [StepContribution: read=3, written=3, filtered=0, readSkips=0, writeSkips=0, processSkips=0, exitStatus=EXECUTING]
2022-05-27 01:22:23.953 DEBUG 20890 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Saving step execution before commit: StepExecution: id=1, version=1, name=chunkStep, status=STARTED, exitStatus=EXECUTING, readCount=3, filterCount=0, writeCount=3 readSkipCount=0, writeSkipCount=0, processSkipCount=0, commitCount=1, rollbackCount=0, exitDescription=
2022-05-27 01:22:24.072 DEBUG 20890 --- [           main] o.s.b.c.step.item.ChunkOrientedTasklet   : Inputs not busy, ended: false
2022-05-27 01:22:24.073 DEBUG 20890 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Applying contribution: [StepContribution: read=3, written=3, filtered=0, readSkips=0, writeSkips=0, processSkips=0, exitStatus=EXECUTING]
2022-05-27 01:22:24.076 DEBUG 20890 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Saving step execution before commit: StepExecution: id=1, version=2, name=chunkStep, status=STARTED, exitStatus=EXECUTING, readCount=6, filterCount=0, writeCount=6 readSkipCount=0, writeSkipCount=0, processSkipCount=0, commitCount=2, rollbackCount=0, exitDescription=
2022-05-27 01:22:24.343 DEBUG 20890 --- [           main] o.s.b.c.step.item.ChunkOrientedTasklet   : Inputs not busy, ended: false
2022-05-27 01:22:24.344 DEBUG 20890 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Applying contribution: [StepContribution: read=3, written=3, filtered=0, readSkips=0, writeSkips=0, processSkips=0, exitStatus=EXECUTING]
2022-05-27 01:22:24.345 DEBUG 20890 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Saving step execution before commit: StepExecution: id=1, version=3, name=chunkStep, status=STARTED, exitStatus=EXECUTING, readCount=9, filterCount=0, writeCount=9 readSkipCount=0, writeSkipCount=0, processSkipCount=0, commitCount=3, rollbackCount=0, exitDescription=
2022-05-27 01:22:24.510 DEBUG 20890 --- [           main] o.s.b.c.step.item.ChunkOrientedTasklet   : Inputs not busy, ended: true
2022-05-27 01:22:24.510 DEBUG 20890 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Applying contribution: [StepContribution: read=1, written=1, filtered=0, readSkips=0, writeSkips=0, processSkips=0, exitStatus=EXECUTING]
2022-05-27 01:22:24.512 DEBUG 20890 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Saving step execution before commit: StepExecution: id=1, version=4, name=chunkStep, status=STARTED, exitStatus=EXECUTING, readCount=10, filterCount=0, writeCount=10 readSkipCount=0, writeSkipCount=0, processSkipCount=0, commitCount=4, rollbackCount=0, exitDescription=
2022-05-27 01:22:24.576 DEBUG 20890 --- [           main] o.s.batch.core.step.AbstractStep         : Step execution success: id=1
2022-05-27 01:22:24.580  INFO 20890 --- [           main] o.s.batch.core.step.AbstractStep         : Step: [chunkStep] executed in 950ms
2022-05-27 01:22:24.698 DEBUG 20890 --- [           main] o.s.batch.core.step.AbstractStep         : Step execution complete: StepExecution: id=1, version=6, name=chunkStep, status=COMPLETED, exitStatus=COMPLETED, readCount=10, filterCount=0, writeCount=10 readSkipCount=0, writeSkipCount=0, processSkipCount=0, commitCount=4, rollbackCount=0
2022-05-27 01:22:24.757  INFO 20890 --- [           main] o.s.b.c.l.support.SimpleJobLauncher      : Job: [SimpleJob: [name=chunkJob]] completed with the following parameters: [{run.id=1}] and the following status: [COMPLETED] in 1s268ms

デヌタはこうなりたした。

mysql> select * from book;
+----------------+---------------------------------------------------------------------------------------------------------+-------+
| isbn           | title                                                                                                   | price |
+----------------+---------------------------------------------------------------------------------------------------------+-------+
| 978-1484237236 | The Definitive Guide to Spring Batch: Modern Finite Batch Processing in the Cloud                       |  7361 |
| 978-1492076988 | Spring Boot: Up and Running: Building Cloud Native Java and Kotlin Applications                         |  6265 |
| 978-4295000198 | やさしく孊べるMySQL運甚・管理入門【5.7察応】                                                            |  2860 |
| 978-4774170206 | MariaDB&MySQL党機胜バむブル                                                                             |  3860 |
| 978-4774182179 | [改蚂新版]Spring入門 ――Javaフレヌムワヌク・より良い蚭蚈ずアヌキテクチャ                                 |  4180 |
| 978-4797393118 | 基瀎からのMySQL 第3版 (基瀎からシリヌズ)                                                                |  6038 |
| 978-4798142470 | Spring培底入門 Spring FrameworkによるJavaアプリケヌション開発                                           |  4400 |
| 978-4798147406 | 詳解MySQL 5.7 止たらぬ進化に乗り遅れないためのテクニカルガむド (NEXT ONE)                               |  3960 |
| 978-4798161488 | MySQL培底入門 第4版 MySQL 8.0察応                                                                       |  4180 |
| 978-4873116389 | 実践ハむパフォヌマンスMySQL 第3版                                                                       |  5280 |
+----------------+---------------------------------------------------------------------------------------------------------+-------+
10 rows in set (0.00 sec)
ItemReaderが䟋倖をスロヌする堎合

次は、ItemReaderが䟋倖をスロヌする堎合です。

たずは、RuntimeExceptionをスロヌしおみたす。

    @Override
    public Book read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
        currentCount++;

        if (currentCount > 7) {
            throw new RuntimeException("Oops!!");
            // throw new Exception("Oops!!");
        }

        if (bookIterator.hasNext()) {
            return bookIterator.next();
        } else {
            return null;
        }
    }

ログ。

2022-05-27 01:23:27.851  INFO 21357 --- [           main] o.s.b.a.b.JobLauncherApplicationRunner   : Running default command line with: []
2022-05-27 01:23:28.190  INFO 21357 --- [           main] o.s.b.c.l.support.SimpleJobLauncher      : Job: [SimpleJob: [name=chunkJob]] launched with the following parameters: [{run.id=2}]
2022-05-27 01:23:28.312  INFO 21357 --- [           main] o.s.batch.core.job.SimpleStepHandler     : Executing step: [chunkStep]
2022-05-27 01:23:28.312 DEBUG 21357 --- [           main] o.s.batch.core.step.AbstractStep         : Executing: id=2
2022-05-27 01:23:28.531 DEBUG 21357 --- [           main] o.s.b.c.step.item.ChunkOrientedTasklet   : Inputs not busy, ended: false
2022-05-27 01:23:28.532 DEBUG 21357 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Applying contribution: [StepContribution: read=3, written=3, filtered=0, readSkips=0, writeSkips=0, processSkips=0, exitStatus=EXECUTING]
2022-05-27 01:23:28.536 DEBUG 21357 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Saving step execution before commit: StepExecution: id=2, version=1, name=chunkStep, status=STARTED, exitStatus=EXECUTING, readCount=3, filterCount=0, writeCount=3 readSkipCount=0, writeSkipCount=0, processSkipCount=0, commitCount=1, rollbackCount=0, exitDescription=
2022-05-27 01:23:28.575 DEBUG 21357 --- [           main] o.s.b.c.step.item.ChunkOrientedTasklet   : Inputs not busy, ended: false
2022-05-27 01:23:28.575 DEBUG 21357 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Applying contribution: [StepContribution: read=3, written=3, filtered=0, readSkips=0, writeSkips=0, processSkips=0, exitStatus=EXECUTING]
2022-05-27 01:23:28.577 DEBUG 21357 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Saving step execution before commit: StepExecution: id=2, version=2, name=chunkStep, status=STARTED, exitStatus=EXECUTING, readCount=6, filterCount=0, writeCount=6 readSkipCount=0, writeSkipCount=0, processSkipCount=0, commitCount=2, rollbackCount=0, exitDescription=
2022-05-27 01:23:28.607 DEBUG 21357 --- [           main] o.s.b.c.step.item.SimpleChunkProvider    : Oops!! : java.lang.RuntimeException
2022-05-27 01:23:28.607 DEBUG 21357 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Applying contribution: [StepContribution: read=1, written=0, filtered=0, readSkips=0, writeSkips=0, processSkips=0, exitStatus=EXECUTING]
2022-05-27 01:23:28.607 DEBUG 21357 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Rollback for RuntimeException: java.lang.RuntimeException: Oops!!
2022-05-27 01:23:28.612 DEBUG 21357 --- [           main] o.s.t.support.TransactionTemplate        : Initiating transaction rollback on application exception

java.lang.RuntimeException: Oops!!
        at org.littlewings.spring.batch.BookItemReader.read(BookItemReader.java:38) ~[classes!/:0.0.1-SNAPSHOT]
        at org.littlewings.spring.batch.BookItemReader.read(BookItemReader.java:12) ~[classes!/:0.0.1-SNAPSHOT]
        at org.littlewings.spring.batch.BookItemReader$$FastClassBySpringCGLIB$$29093ae.invoke(<generated>) ~[classes!/:0.0.1-SNAPSHOT]
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:793) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:137) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.littlewings.spring.batch.BookItemReader$$EnhancerBySpringCGLIB$$9a856c3.read(<generated>) ~[classes!/:0.0.1-SNAPSHOT]
        at org.springframework.batch.core.step.item.SimpleChunkProvider.doRead(SimpleChunkProvider.java:99) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.item.SimpleChunkProvider.read(SimpleChunkProvider.java:180) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.item.SimpleChunkProvider$1.doInIteration(SimpleChunkProvider.java:126) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:375) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:145) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.item.SimpleChunkProvider.provide(SimpleChunkProvider.java:118) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:71) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:407) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:331) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140) ~[spring-tx-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:273) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:82) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:375) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:145) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:258) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:208) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:152) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.AbstractJob.handleStep(AbstractJob.java:413) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.SimpleJob.doExecute(SimpleJob.java:136) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:320) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:149) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50) ~[spring-core-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:140) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:128) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at jdk.proxy2/jdk.proxy2.$Proxy83.run(Unknown Source) ~[na:na]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.execute(JobLauncherApplicationRunner.java:199) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.executeLocalJobs(JobLauncherApplicationRunner.java:173) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.launchJobFromProperties(JobLauncherApplicationRunner.java:160) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.run(JobLauncherApplicationRunner.java:155) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.run(JobLauncherApplicationRunner.java:150) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:762) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:752) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.littlewings.spring.batch.App.main(App.java:11) ~[classes!/:0.0.1-SNAPSHOT]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
        at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:108) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:58) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:65) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]

2022-05-27 01:23:28.619 ERROR 21357 --- [           main] o.s.batch.core.step.AbstractStep         : Encountered an error executing step chunkStep in job chunkJob

java.lang.RuntimeException: Oops!!
        at org.littlewings.spring.batch.BookItemReader.read(BookItemReader.java:38) ~[classes!/:0.0.1-SNAPSHOT]
        at org.littlewings.spring.batch.BookItemReader.read(BookItemReader.java:12) ~[classes!/:0.0.1-SNAPSHOT]
        at org.littlewings.spring.batch.BookItemReader$$FastClassBySpringCGLIB$$29093ae.invoke(<generated>) ~[classes!/:0.0.1-SNAPSHOT]
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:793) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:137) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.littlewings.spring.batch.BookItemReader$$EnhancerBySpringCGLIB$$9a856c3.read(<generated>) ~[classes!/:0.0.1-SNAPSHOT]
        at org.springframework.batch.core.step.item.SimpleChunkProvider.doRead(SimpleChunkProvider.java:99) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.item.SimpleChunkProvider.read(SimpleChunkProvider.java:180) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.item.SimpleChunkProvider$1.doInIteration(SimpleChunkProvider.java:126) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:375) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:145) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.item.SimpleChunkProvider.provide(SimpleChunkProvider.java:118) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:71) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:407) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:331) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140) ~[spring-tx-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:273) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:82) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:375) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:145) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:258) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:208) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:152) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.AbstractJob.handleStep(AbstractJob.java:413) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.SimpleJob.doExecute(SimpleJob.java:136) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:320) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:149) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50) ~[spring-core-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:140) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:128) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at jdk.proxy2/jdk.proxy2.$Proxy83.run(Unknown Source) ~[na:na]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.execute(JobLauncherApplicationRunner.java:199) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.executeLocalJobs(JobLauncherApplicationRunner.java:173) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.launchJobFromProperties(JobLauncherApplicationRunner.java:160) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.run(JobLauncherApplicationRunner.java:155) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.run(JobLauncherApplicationRunner.java:150) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:762) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:752) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.littlewings.spring.batch.App.main(App.java:11) ~[classes!/:0.0.1-SNAPSHOT]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
        at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:108) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:58) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:65) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]

2022-05-27 01:23:28.625  INFO 21357 --- [           main] o.s.batch.core.step.AbstractStep         : Step: [chunkStep] executed in 313ms
2022-05-27 01:23:28.658 DEBUG 21357 --- [           main] o.s.batch.core.step.AbstractStep         : Step execution complete: StepExecution: id=2, version=4, name=chunkStep, status=FAILED, exitStatus=FAILED, readCount=7, filterCount=0, writeCount=6 readSkipCount=0, writeSkipCount=0, processSkipCount=0, commitCount=2, rollbackCount=1
2022-05-27 01:23:28.693  INFO 21357 --- [           main] o.s.b.c.l.support.SimpleJobLauncher      : Job: [SimpleJob: [name=chunkJob]] completed with the following parameters: [{run.id=2}] and the following status: [FAILED] in 448ms

ロヌルバックを衚すログが出力されおいたす。ちなみに、DEBUGレベルですね。

2022-05-27 01:23:28.607 DEBUG 21357 --- [           main] o.s.b.c.step.item.SimpleChunkProvider    : Oops!! : java.lang.RuntimeException
2022-05-27 01:23:28.607 DEBUG 21357 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Applying contribution: [StepContribution: read=1, written=0, filtered=0, readSkips=0, writeSkips=0, processSkips=0, exitStatus=EXECUTING]
2022-05-27 01:23:28.607 DEBUG 21357 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Rollback for RuntimeException: java.lang.RuntimeException: Oops!!
2022-05-27 01:23:28.612 DEBUG 21357 --- [           main] o.s.t.support.TransactionTemplate        : Initiating transaction rollback on application exception

java.lang.RuntimeException: Oops!!

デヌタは、チャンク2぀分だけが入っおいたすね。3぀目のチャンクは入っおいたせん。

mysql> select * from book;
+----------------+---------------------------------------------------------------------------------------------------------+-------+
| isbn           | title                                                                                                   | price |
+----------------+---------------------------------------------------------------------------------------------------------+-------+
| 978-1484237236 | The Definitive Guide to Spring Batch: Modern Finite Batch Processing in the Cloud                       |  7361 |
| 978-1492076988 | Spring Boot: Up and Running: Building Cloud Native Java and Kotlin Applications                         |  6265 |
| 978-4774182179 | [改蚂新版]Spring入門 ――Javaフレヌムワヌク・より良い蚭蚈ずアヌキテクチャ                                 |  4180 |
| 978-4797393118 | 基瀎からのMySQL 第3版 (基瀎からシリヌズ)                                                                |  6038 |
| 978-4798142470 | Spring培底入門 Spring FrameworkによるJavaアプリケヌション開発                                           |  4400 |
| 978-4798161488 | MySQL培底入門 第4版 MySQL 8.0察応                                                                       |  4180 |
+----------------+---------------------------------------------------------------------------------------------------------+-------+
6 rows in set (0.01 sec)

今床は、Exceptionをスロヌしおみたす。

    @Override
    public Book read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
        currentCount++;

        if (currentCount > 7) {
            // throw new RuntimeException("Oops!!");
            throw new Exception("Oops!!");
        }

        if (bookIterator.hasNext()) {
            return bookIterator.next();
        } else {
            return null;
        }
    }

ログ。

2022-05-27 01:25:29.476  INFO 21604 --- [           main] o.s.b.a.b.JobLauncherApplicationRunner   : Running default command line with: []
2022-05-27 01:25:29.829  INFO 21604 --- [           main] o.s.b.c.l.support.SimpleJobLauncher      : Job: [SimpleJob: [name=chunkJob]] launched with the following parameters: [{run.id=3}]
2022-05-27 01:25:29.931  INFO 21604 --- [           main] o.s.batch.core.job.SimpleStepHandler     : Executing step: [chunkStep]
2022-05-27 01:25:29.932 DEBUG 21604 --- [           main] o.s.batch.core.step.AbstractStep         : Executing: id=3
2022-05-27 01:25:30.098 DEBUG 21604 --- [           main] o.s.b.c.step.item.ChunkOrientedTasklet   : Inputs not busy, ended: false
2022-05-27 01:25:30.098 DEBUG 21604 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Applying contribution: [StepContribution: read=3, written=3, filtered=0, readSkips=0, writeSkips=0, processSkips=0, exitStatus=EXECUTING]
2022-05-27 01:25:30.101 DEBUG 21604 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Saving step execution before commit: StepExecution: id=3, version=1, name=chunkStep, status=STARTED, exitStatus=EXECUTING, readCount=3, filterCount=0, writeCount=3 readSkipCount=0, writeSkipCount=0, processSkipCount=0, commitCount=1, rollbackCount=0, exitDescription=
2022-05-27 01:25:30.145 DEBUG 21604 --- [           main] o.s.b.c.step.item.ChunkOrientedTasklet   : Inputs not busy, ended: false
2022-05-27 01:25:30.145 DEBUG 21604 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Applying contribution: [StepContribution: read=3, written=3, filtered=0, readSkips=0, writeSkips=0, processSkips=0, exitStatus=EXECUTING]
2022-05-27 01:25:30.147 DEBUG 21604 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Saving step execution before commit: StepExecution: id=3, version=2, name=chunkStep, status=STARTED, exitStatus=EXECUTING, readCount=6, filterCount=0, writeCount=6 readSkipCount=0, writeSkipCount=0, processSkipCount=0, commitCount=2, rollbackCount=0, exitDescription=
2022-05-27 01:25:30.194 DEBUG 21604 --- [           main] o.s.b.c.step.item.SimpleChunkProvider    : Oops!! : java.lang.Exception
2022-05-27 01:25:30.195 DEBUG 21604 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Applying contribution: [StepContribution: read=1, written=0, filtered=0, readSkips=0, writeSkips=0, processSkips=0, exitStatus=EXECUTING]
2022-05-27 01:25:30.195 DEBUG 21604 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Rollback for RuntimeException: org.springframework.batch.repeat.RepeatException: Exception in batch process; nested exception is java.lang.Exception: Oops!!
2022-05-27 01:25:30.201 DEBUG 21604 --- [           main] o.s.t.support.TransactionTemplate        : Initiating transaction rollback on application exception

org.springframework.batch.repeat.RepeatException: Exception in batch process; nested exception is java.lang.Exception: Oops!!
        at org.springframework.batch.repeat.support.RepeatTemplate.rethrow(RepeatTemplate.java:320) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:256) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:145) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.item.SimpleChunkProvider.provide(SimpleChunkProvider.java:118) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:71) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:407) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:331) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140) ~[spring-tx-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:273) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:82) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:375) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:145) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:258) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:208) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:152) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.AbstractJob.handleStep(AbstractJob.java:413) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.SimpleJob.doExecute(SimpleJob.java:136) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:320) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:149) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50) ~[spring-core-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:140) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:128) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at jdk.proxy2/jdk.proxy2.$Proxy83.run(Unknown Source) ~[na:na]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.execute(JobLauncherApplicationRunner.java:199) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.executeLocalJobs(JobLauncherApplicationRunner.java:173) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.launchJobFromProperties(JobLauncherApplicationRunner.java:160) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.run(JobLauncherApplicationRunner.java:155) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.run(JobLauncherApplicationRunner.java:150) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:762) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:752) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.littlewings.spring.batch.App.main(App.java:11) ~[classes!/:0.0.1-SNAPSHOT]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
        at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:108) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:58) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:65) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
Caused by: java.lang.Exception: Oops!!
        at org.littlewings.spring.batch.BookItemReader.read(BookItemReader.java:39) ~[classes!/:0.0.1-SNAPSHOT]
        at org.littlewings.spring.batch.BookItemReader.read(BookItemReader.java:12) ~[classes!/:0.0.1-SNAPSHOT]
        at org.littlewings.spring.batch.BookItemReader$$FastClassBySpringCGLIB$$29093ae.invoke(<generated>) ~[classes!/:0.0.1-SNAPSHOT]
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:793) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:137) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.littlewings.spring.batch.BookItemReader$$EnhancerBySpringCGLIB$$b4130ec4.read(<generated>) ~[classes!/:0.0.1-SNAPSHOT]
        at org.springframework.batch.core.step.item.SimpleChunkProvider.doRead(SimpleChunkProvider.java:99) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.item.SimpleChunkProvider.read(SimpleChunkProvider.java:180) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.item.SimpleChunkProvider$1.doInIteration(SimpleChunkProvider.java:126) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:375) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        ... 50 common frames omitted

2022-05-27 01:25:30.208 ERROR 21604 --- [           main] o.s.batch.core.step.AbstractStep         : Encountered an error executing step chunkStep in job chunkJob

java.lang.Exception: Oops!!
        at org.littlewings.spring.batch.BookItemReader.read(BookItemReader.java:39) ~[classes!/:0.0.1-SNAPSHOT]
        at org.littlewings.spring.batch.BookItemReader.read(BookItemReader.java:12) ~[classes!/:0.0.1-SNAPSHOT]
        at org.littlewings.spring.batch.BookItemReader$$FastClassBySpringCGLIB$$29093ae.invoke(<generated>) ~[classes!/:0.0.1-SNAPSHOT]
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:793) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:137) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.littlewings.spring.batch.BookItemReader$$EnhancerBySpringCGLIB$$b4130ec4.read(<generated>) ~[classes!/:0.0.1-SNAPSHOT]
        at org.springframework.batch.core.step.item.SimpleChunkProvider.doRead(SimpleChunkProvider.java:99) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.item.SimpleChunkProvider.read(SimpleChunkProvider.java:180) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.item.SimpleChunkProvider$1.doInIteration(SimpleChunkProvider.java:126) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:375) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:145) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.item.SimpleChunkProvider.provide(SimpleChunkProvider.java:118) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:71) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:407) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:331) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140) ~[spring-tx-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:273) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:82) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:375) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:145) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:258) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:208) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:152) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.AbstractJob.handleStep(AbstractJob.java:413) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.SimpleJob.doExecute(SimpleJob.java:136) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:320) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:149) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50) ~[spring-core-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:140) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:128) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at jdk.proxy2/jdk.proxy2.$Proxy83.run(Unknown Source) ~[na:na]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.execute(JobLauncherApplicationRunner.java:199) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.executeLocalJobs(JobLauncherApplicationRunner.java:173) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.launchJobFromProperties(JobLauncherApplicationRunner.java:160) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.run(JobLauncherApplicationRunner.java:155) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.run(JobLauncherApplicationRunner.java:150) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:762) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:752) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.littlewings.spring.batch.App.main(App.java:11) ~[classes!/:0.0.1-SNAPSHOT]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
        at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:108) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:58) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:65) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]

2022-05-27 01:25:30.215  INFO 21604 --- [           main] o.s.batch.core.step.AbstractStep         : Step: [chunkStep] executed in 283ms
2022-05-27 01:25:30.258 DEBUG 21604 --- [           main] o.s.batch.core.step.AbstractStep         : Step execution complete: StepExecution: id=3, version=4, name=chunkStep, status=FAILED, exitStatus=FAILED, readCount=7, filterCount=0, writeCount=6 readSkipCount=0, writeSkipCount=0, processSkipCount=0, commitCount=2, rollbackCount=1
2022-05-27 01:25:30.315  INFO 21604 --- [           main] o.s.b.c.l.support.SimpleJobLauncher      : Job: [SimpleJob: [name=chunkJob]] completed with the following parameters: [{run.id=3}] and the following status: [FAILED] in 412ms

ロヌルバックされたようです。

登録されたデヌタ数には、倉化がありたせん。

mysql> select * from book;
+----------------+---------------------------------------------------------------------------------------------------------+-------+
| isbn           | title                                                                                                   | price |
+----------------+---------------------------------------------------------------------------------------------------------+-------+
| 978-1484237236 | The Definitive Guide to Spring Batch: Modern Finite Batch Processing in the Cloud                       |  7361 |
| 978-1492076988 | Spring Boot: Up and Running: Building Cloud Native Java and Kotlin Applications                         |  6265 |
| 978-4774182179 | [改蚂新版]Spring入門 ――Javaフレヌムワヌク・より良い蚭蚈ずアヌキテクチャ                                 |  4180 |
| 978-4797393118 | 基瀎からのMySQL 第3版 (基瀎からシリヌズ)                                                                |  6038 |
| 978-4798142470 | Spring培底入門 Spring FrameworkによるJavaアプリケヌション開発                                           |  4400 |
| 978-4798161488 | MySQL培底入門 第4版 MySQL 8.0察応                                                                       |  4180 |
+----------------+---------------------------------------------------------------------------------------------------------+-------+
6 rows in set (0.00 sec)

ログに関しおは、よくよく芋るずスタックトレヌスが倉わっおいたす。

RuntimeExceptionの堎合。

2022-05-27 01:23:28.607 DEBUG 21357 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Rollback for RuntimeException: java.lang.RuntimeException: Oops!!
2022-05-27 01:23:28.612 DEBUG 21357 --- [           main] o.s.t.support.TransactionTemplate        : Initiating transaction rollback on application exception

java.lang.RuntimeException: Oops!!
        at org.littlewings.spring.batch.BookItemReader.read(BookItemReader.java:38) ~[classes!/:0.0.1-SNAPSHOT]
        at org.littlewings.spring.batch.BookItemReader.read(BookItemReader.java:12) ~[classes!/:0.0.1-SNAPSHOT]
        at org.littlewings.spring.batch.BookItemReader$$FastClassBySpringCGLIB$$29093ae.invoke(<generated>) ~[classes!/:0.0.1-SNAPSHOT]
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.20.jar!/:5.3.20]

〜省略〜

Exceptionの堎合。

2022-05-27 01:25:30.195 DEBUG 21604 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Rollback for RuntimeException: org.springframework.batch.repeat.RepeatException: Exception in batch process; nested exception is java.lang.Exception: Oops!!
2022-05-27 01:25:30.201 DEBUG 21604 --- [           main] o.s.t.support.TransactionTemplate        : Initiating transaction rollback on application exception

org.springframework.batch.repeat.RepeatException: Exception in batch process; nested exception is java.lang.Exception: Oops!!
        at org.springframework.batch.repeat.support.RepeatTemplate.rethrow(RepeatTemplate.java:320) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:256) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:145) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.item.SimpleChunkProvider.provide(SimpleChunkProvider.java:118) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:71) ~[spring-batch-core-4.3.6.jar!/:4.3.6]

〜省略〜

Caused by: java.lang.Exception: Oops!!
        at org.littlewings.spring.batch.BookItemReader.read(BookItemReader.java:39) ~[classes!/:0.0.1-SNAPSHOT]
        at org.littlewings.spring.batch.BookItemReader.read(BookItemReader.java:12) ~[classes!/:0.0.1-SNAPSHOT]
        at org.littlewings.spring.batch.BookItemReader$$FastClassBySpringCGLIB$$29093ae.invoke(<generated>) ~[classes!/:0.0.1-SNAPSHOT]
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.20.jar!/:5.3.20]

〜省略〜

よく芋るず、Exceptionの方はネストした䟋倖になっおいたす。そしおRuntimeExceptionでロヌルバックしたこずになっおいたす。

2022-05-27 01:25:30.195 DEBUG 21604 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Rollback for RuntimeException: org.springframework.batch.repeat.RepeatException: Exception in batch process; nested exception is java.lang.Exception: Oops!!

どうやら、ラップしお再スロヌしおいるようですね。RepeatExceptionをスロヌしたこずになっおいたす。

2022-05-27 01:25:30.201 DEBUG 21604 --- [           main] o.s.t.support.TransactionTemplate        : Initiating transaction rollback on application exception

org.springframework.batch.repeat.RepeatException: Exception in batch process; nested exception is java.lang.Exception: Oops!!
        at org.springframework.batch.repeat.support.RepeatTemplate.rethrow(RepeatTemplate.java:320) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]

RuntimeExceptionをスロヌした時の方が、玠盎な動きですね。

結論ずしおは、RuntimeExceptionでもExceptionでもロヌルバックするこずがわかりたした。

ItemReaderは、いったん元に戻したす。

    @Override
    public Book read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
        currentCount++;

        if (currentCount > 7) {
            // throw new RuntimeException("Oops!!");
            // throw new Exception("Oops!!");
        }

        if (bookIterator.hasNext()) {
            return bookIterator.next();
        } else {
            return null;
        }
    }
ItemProcessorが䟋倖をスロヌする堎合

次は、ItemProcessorに移りたしょう。

RuntimeExceptionをスロヌしおみたす。

    @Override
    public Book process(Book item) throws Exception {
        currentCount++;

        if (currentCount > 7) {
            throw new RuntimeException("Oops!!");
            // throw new Exception("Oops!!");
        }

        return item;
    }

実行ログ。

2022-05-27 01:29:23.714  INFO 21982 --- [           main] o.s.b.a.b.JobLauncherApplicationRunner   : Running default command line with: []
2022-05-27 01:29:24.011  INFO 21982 --- [           main] o.s.b.c.l.support.SimpleJobLauncher      : Job: [SimpleJob: [name=chunkJob]] launched with the following parameters: [{run.id=4}]
2022-05-27 01:29:24.163  INFO 21982 --- [           main] o.s.batch.core.job.SimpleStepHandler     : Executing step: [chunkStep]
2022-05-27 01:29:24.163 DEBUG 21982 --- [           main] o.s.batch.core.step.AbstractStep         : Executing: id=4
2022-05-27 01:29:24.390 DEBUG 21982 --- [           main] o.s.b.c.step.item.ChunkOrientedTasklet   : Inputs not busy, ended: false
2022-05-27 01:29:24.390 DEBUG 21982 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Applying contribution: [StepContribution: read=3, written=3, filtered=0, readSkips=0, writeSkips=0, processSkips=0, exitStatus=EXECUTING]
2022-05-27 01:29:24.393 DEBUG 21982 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Saving step execution before commit: StepExecution: id=4, version=1, name=chunkStep, status=STARTED, exitStatus=EXECUTING, readCount=3, filterCount=0, writeCount=3 readSkipCount=0, writeSkipCount=0, processSkipCount=0, commitCount=1, rollbackCount=0, exitDescription=
2022-05-27 01:29:24.429 DEBUG 21982 --- [           main] o.s.b.c.step.item.ChunkOrientedTasklet   : Inputs not busy, ended: false
2022-05-27 01:29:24.429 DEBUG 21982 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Applying contribution: [StepContribution: read=3, written=3, filtered=0, readSkips=0, writeSkips=0, processSkips=0, exitStatus=EXECUTING]
2022-05-27 01:29:24.431 DEBUG 21982 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Saving step execution before commit: StepExecution: id=4, version=2, name=chunkStep, status=STARTED, exitStatus=EXECUTING, readCount=6, filterCount=0, writeCount=6 readSkipCount=0, writeSkipCount=0, processSkipCount=0, commitCount=2, rollbackCount=0, exitDescription=
2022-05-27 01:29:24.461 DEBUG 21982 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Applying contribution: [StepContribution: read=3, written=0, filtered=0, readSkips=0, writeSkips=0, processSkips=0, exitStatus=EXECUTING]
2022-05-27 01:29:24.461 DEBUG 21982 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Rollback for RuntimeException: java.lang.RuntimeException: Oops!!
2022-05-27 01:29:24.465 DEBUG 21982 --- [           main] o.s.t.support.TransactionTemplate        : Initiating transaction rollback on application exception

java.lang.RuntimeException: Oops!!
        at org.littlewings.spring.batch.BookItemProcessor.process(BookItemProcessor.java:13) ~[classes!/:0.0.1-SNAPSHOT]
        at org.littlewings.spring.batch.BookItemProcessor.process(BookItemProcessor.java:5) ~[classes!/:0.0.1-SNAPSHOT]
        at org.littlewings.spring.batch.BookItemProcessor$$FastClassBySpringCGLIB$$775ca5c7.invoke(<generated>) ~[classes!/:0.0.1-SNAPSHOT]
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:793) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:137) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.littlewings.spring.batch.BookItemProcessor$$EnhancerBySpringCGLIB$$acf7a11d.process(<generated>) ~[classes!/:0.0.1-SNAPSHOT]
        at org.springframework.batch.core.step.item.SimpleChunkProcessor.doProcess(SimpleChunkProcessor.java:134) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.item.SimpleChunkProcessor.transform(SimpleChunkProcessor.java:319) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.item.SimpleChunkProcessor.process(SimpleChunkProcessor.java:210) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:77) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:407) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:331) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140) ~[spring-tx-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:273) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:82) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:375) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:145) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:258) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:208) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:152) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.AbstractJob.handleStep(AbstractJob.java:413) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.SimpleJob.doExecute(SimpleJob.java:136) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:320) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:149) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50) ~[spring-core-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:140) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:128) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at jdk.proxy2/jdk.proxy2.$Proxy83.run(Unknown Source) ~[na:na]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.execute(JobLauncherApplicationRunner.java:199) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.executeLocalJobs(JobLauncherApplicationRunner.java:173) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.launchJobFromProperties(JobLauncherApplicationRunner.java:160) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.run(JobLauncherApplicationRunner.java:155) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.run(JobLauncherApplicationRunner.java:150) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:762) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:752) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.littlewings.spring.batch.App.main(App.java:11) ~[classes!/:0.0.1-SNAPSHOT]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
        at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:108) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:58) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:65) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]

2022-05-27 01:29:24.471 ERROR 21982 --- [           main] o.s.batch.core.step.AbstractStep         : Encountered an error executing step chunkStep in job chunkJob

java.lang.RuntimeException: Oops!!
        at org.littlewings.spring.batch.BookItemProcessor.process(BookItemProcessor.java:13) ~[classes!/:0.0.1-SNAPSHOT]
        at org.littlewings.spring.batch.BookItemProcessor.process(BookItemProcessor.java:5) ~[classes!/:0.0.1-SNAPSHOT]
        at org.littlewings.spring.batch.BookItemProcessor$$FastClassBySpringCGLIB$$775ca5c7.invoke(<generated>) ~[classes!/:0.0.1-SNAPSHOT]
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:793) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:137) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.littlewings.spring.batch.BookItemProcessor$$EnhancerBySpringCGLIB$$acf7a11d.process(<generated>) ~[classes!/:0.0.1-SNAPSHOT]
        at org.springframework.batch.core.step.item.SimpleChunkProcessor.doProcess(SimpleChunkProcessor.java:134) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.item.SimpleChunkProcessor.transform(SimpleChunkProcessor.java:319) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.item.SimpleChunkProcessor.process(SimpleChunkProcessor.java:210) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:77) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:407) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:331) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140) ~[spring-tx-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:273) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:82) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:375) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:145) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:258) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:208) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:152) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.AbstractJob.handleStep(AbstractJob.java:413) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.SimpleJob.doExecute(SimpleJob.java:136) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:320) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:149) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50) ~[spring-core-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:140) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:128) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at jdk.proxy2/jdk.proxy2.$Proxy83.run(Unknown Source) ~[na:na]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.execute(JobLauncherApplicationRunner.java:199) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.executeLocalJobs(JobLauncherApplicationRunner.java:173) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.launchJobFromProperties(JobLauncherApplicationRunner.java:160) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.run(JobLauncherApplicationRunner.java:155) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.run(JobLauncherApplicationRunner.java:150) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:762) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:752) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.littlewings.spring.batch.App.main(App.java:11) ~[classes!/:0.0.1-SNAPSHOT]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
        at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:108) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:58) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:65) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]

2022-05-27 01:29:24.475  INFO 21982 --- [           main] o.s.batch.core.step.AbstractStep         : Step: [chunkStep] executed in 312ms
2022-05-27 01:29:24.502 DEBUG 21982 --- [           main] o.s.batch.core.step.AbstractStep         : Step execution complete: StepExecution: id=4, version=4, name=chunkStep, status=FAILED, exitStatus=FAILED, readCount=9, filterCount=0, writeCount=6 readSkipCount=0, writeSkipCount=0, processSkipCount=0, commitCount=2, rollbackCount=1
2022-05-27 01:29:24.534  INFO 21982 --- [           main] o.s.b.c.l.support.SimpleJobLauncher      : Job: [SimpleJob: [name=chunkJob]] completed with the following parameters: [{run.id=4}] and the following status: [FAILED] in 466ms

こちらもロヌルバックしおいるようです。

2022-05-27 01:29:24.461 DEBUG 21982 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Rollback for RuntimeException: java.lang.RuntimeException: Oops!!
2022-05-27 01:29:24.465 DEBUG 21982 --- [           main] o.s.t.support.TransactionTemplate        : Initiating transaction rollback on application exception

java.lang.RuntimeException: Oops!!
        at org.littlewings.spring.batch.BookItemProcessor.process(BookItemProcessor.java:13) ~[classes!/:0.0.1-SNAPSHOT]
        at org.littlewings.spring.batch.BookItemProcessor.process(BookItemProcessor.java:5) ~[classes!/:0.0.1-SNAPSHOT]
        at org.littlewings.spring.batch.BookItemProcessor$$FastClassBySpringCGLIB$$775ca5c7.invoke(<generated>) ~[classes!/:0.0.1-SNAPSHOT]
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.20.jar!/:5.3.20]

デヌタ。2぀のチャンク分のデヌタたでが入っおいたすね。

mysql> select * from book;
+----------------+---------------------------------------------------------------------------------------------------------+-------+
| isbn           | title                                                                                                   | price |
+----------------+---------------------------------------------------------------------------------------------------------+-------+
| 978-1484237236 | The Definitive Guide to Spring Batch: Modern Finite Batch Processing in the Cloud                       |  7361 |
| 978-1492076988 | Spring Boot: Up and Running: Building Cloud Native Java and Kotlin Applications                         |  6265 |
| 978-4774182179 | [改蚂新版]Spring入門 ――Javaフレヌムワヌク・より良い蚭蚈ずアヌキテクチャ                                 |  4180 |
| 978-4797393118 | 基瀎からのMySQL 第3版 (基瀎からシリヌズ)                                                                |  6038 |
| 978-4798142470 | Spring培底入門 Spring FrameworkによるJavaアプリケヌション開発                                           |  4400 |
| 978-4798161488 | MySQL培底入門 第4版 MySQL 8.0察応                                                                       |  4180 |
+----------------+---------------------------------------------------------------------------------------------------------+-------+
6 rows in set (0.00 sec)

Exceptionをスロヌしおみたす。

    @Override
    public Book process(Book item) throws Exception {
        currentCount++;

        if (currentCount > 7) {
            // throw new RuntimeException("Oops!!");
            throw new Exception("Oops!!");
        }

        return item;
    }

ログ。

2022-05-27 01:30:47.367  INFO 22148 --- [           main] o.s.b.a.b.JobLauncherApplicationRunner   : Running default command line with: []
2022-05-27 01:30:47.672  INFO 22148 --- [           main] o.s.b.c.l.support.SimpleJobLauncher      : Job: [SimpleJob: [name=chunkJob]] launched with the following parameters: [{run.id=5}]
2022-05-27 01:30:47.815  INFO 22148 --- [           main] o.s.batch.core.job.SimpleStepHandler     : Executing step: [chunkStep]
2022-05-27 01:30:47.815 DEBUG 22148 --- [           main] o.s.batch.core.step.AbstractStep         : Executing: id=5
2022-05-27 01:30:48.011 DEBUG 22148 --- [           main] o.s.b.c.step.item.ChunkOrientedTasklet   : Inputs not busy, ended: false
2022-05-27 01:30:48.011 DEBUG 22148 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Applying contribution: [StepContribution: read=3, written=3, filtered=0, readSkips=0, writeSkips=0, processSkips=0, exitStatus=EXECUTING]
2022-05-27 01:30:48.014 DEBUG 22148 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Saving step execution before commit: StepExecution: id=5, version=1, name=chunkStep, status=STARTED, exitStatus=EXECUTING, readCount=3, filterCount=0, writeCount=3 readSkipCount=0, writeSkipCount=0, processSkipCount=0, commitCount=1, rollbackCount=0, exitDescription=
2022-05-27 01:30:48.049 DEBUG 22148 --- [           main] o.s.b.c.step.item.ChunkOrientedTasklet   : Inputs not busy, ended: false
2022-05-27 01:30:48.050 DEBUG 22148 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Applying contribution: [StepContribution: read=3, written=3, filtered=0, readSkips=0, writeSkips=0, processSkips=0, exitStatus=EXECUTING]
2022-05-27 01:30:48.052 DEBUG 22148 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Saving step execution before commit: StepExecution: id=5, version=2, name=chunkStep, status=STARTED, exitStatus=EXECUTING, readCount=6, filterCount=0, writeCount=6 readSkipCount=0, writeSkipCount=0, processSkipCount=0, commitCount=2, rollbackCount=0, exitDescription=
2022-05-27 01:30:48.083 DEBUG 22148 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Applying contribution: [StepContribution: read=3, written=0, filtered=0, readSkips=0, writeSkips=0, processSkips=0, exitStatus=EXECUTING]
2022-05-27 01:30:48.083 DEBUG 22148 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Rollback for Exception: java.lang.Exception: Oops!!
2022-05-27 01:30:48.088 DEBUG 22148 --- [           main] o.s.t.support.TransactionTemplate        : Initiating transaction rollback on application exception

org.springframework.batch.core.step.tasklet.UncheckedTransactionException: java.lang.Exception: Oops!!
        at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:487) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:331) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140) ~[spring-tx-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:273) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:82) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:375) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:145) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:258) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:208) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:152) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.AbstractJob.handleStep(AbstractJob.java:413) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.SimpleJob.doExecute(SimpleJob.java:136) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:320) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:149) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50) ~[spring-core-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:140) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:128) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at jdk.proxy2/jdk.proxy2.$Proxy83.run(Unknown Source) ~[na:na]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.execute(JobLauncherApplicationRunner.java:199) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.executeLocalJobs(JobLauncherApplicationRunner.java:173) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.launchJobFromProperties(JobLauncherApplicationRunner.java:160) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.run(JobLauncherApplicationRunner.java:155) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.run(JobLauncherApplicationRunner.java:150) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:762) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:752) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.littlewings.spring.batch.App.main(App.java:11) ~[classes!/:0.0.1-SNAPSHOT]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
        at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:108) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:58) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:65) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
Caused by: java.lang.Exception: Oops!!
        at org.littlewings.spring.batch.BookItemProcessor.process(BookItemProcessor.java:14) ~[classes!/:0.0.1-SNAPSHOT]
        at org.littlewings.spring.batch.BookItemProcessor.process(BookItemProcessor.java:5) ~[classes!/:0.0.1-SNAPSHOT]
        at org.littlewings.spring.batch.BookItemProcessor$$FastClassBySpringCGLIB$$775ca5c7.invoke(<generated>) ~[classes!/:0.0.1-SNAPSHOT]
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:793) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:137) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.littlewings.spring.batch.BookItemProcessor$$EnhancerBySpringCGLIB$$acf7a11d.process(<generated>) ~[classes!/:0.0.1-SNAPSHOT]
        at org.springframework.batch.core.step.item.SimpleChunkProcessor.doProcess(SimpleChunkProcessor.java:134) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.item.SimpleChunkProcessor.transform(SimpleChunkProcessor.java:319) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.item.SimpleChunkProcessor.process(SimpleChunkProcessor.java:210) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:77) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:407) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        ... 46 common frames omitted

2022-05-27 01:30:48.094 ERROR 22148 --- [           main] o.s.batch.core.step.AbstractStep         : Encountered an error executing step chunkStep in job chunkJob

java.lang.Exception: Oops!!
        at org.littlewings.spring.batch.BookItemProcessor.process(BookItemProcessor.java:14) ~[classes!/:0.0.1-SNAPSHOT]
        at org.littlewings.spring.batch.BookItemProcessor.process(BookItemProcessor.java:5) ~[classes!/:0.0.1-SNAPSHOT]
        at org.littlewings.spring.batch.BookItemProcessor$$FastClassBySpringCGLIB$$775ca5c7.invoke(<generated>) ~[classes!/:0.0.1-SNAPSHOT]
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:793) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:137) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.littlewings.spring.batch.BookItemProcessor$$EnhancerBySpringCGLIB$$acf7a11d.process(<generated>) ~[classes!/:0.0.1-SNAPSHOT]
        at org.springframework.batch.core.step.item.SimpleChunkProcessor.doProcess(SimpleChunkProcessor.java:134) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.item.SimpleChunkProcessor.transform(SimpleChunkProcessor.java:319) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.item.SimpleChunkProcessor.process(SimpleChunkProcessor.java:210) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:77) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:407) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:331) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140) ~[spring-tx-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:273) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:82) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:375) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:145) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:258) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:208) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:152) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.AbstractJob.handleStep(AbstractJob.java:413) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.SimpleJob.doExecute(SimpleJob.java:136) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:320) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:149) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50) ~[spring-core-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:140) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:128) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at jdk.proxy2/jdk.proxy2.$Proxy83.run(Unknown Source) ~[na:na]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.execute(JobLauncherApplicationRunner.java:199) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.executeLocalJobs(JobLauncherApplicationRunner.java:173) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.launchJobFromProperties(JobLauncherApplicationRunner.java:160) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.run(JobLauncherApplicationRunner.java:155) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.run(JobLauncherApplicationRunner.java:150) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:762) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:752) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.littlewings.spring.batch.App.main(App.java:11) ~[classes!/:0.0.1-SNAPSHOT]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
        at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:108) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:58) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:65) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]

2022-05-27 01:30:48.100  INFO 22148 --- [           main] o.s.batch.core.step.AbstractStep         : Step: [chunkStep] executed in 284ms
2022-05-27 01:30:48.154 DEBUG 22148 --- [           main] o.s.batch.core.step.AbstractStep         : Step execution complete: StepExecution: id=5, version=4, name=chunkStep, status=FAILED, exitStatus=FAILED, readCount=9, filterCount=0, writeCount=6 readSkipCount=0, writeSkipCount=0, processSkipCount=0, commitCount=2, rollbackCount=1
2022-05-27 01:30:48.205  INFO 22148 --- [           main] o.s.b.c.l.support.SimpleJobLauncher      : Job: [SimpleJob: [name=chunkJob]] completed with the following parameters: [{run.id=5}] and the following status: [FAILED] in 455ms

ロヌルバックされたようです。

デヌタ。

mysql> select * from book;
+----------------+---------------------------------------------------------------------------------------------------------+-------+
| isbn           | title                                                                                                   | price |
+----------------+---------------------------------------------------------------------------------------------------------+-------+
| 978-1484237236 | The Definitive Guide to Spring Batch: Modern Finite Batch Processing in the Cloud                       |  7361 |
| 978-1492076988 | Spring Boot: Up and Running: Building Cloud Native Java and Kotlin Applications                         |  6265 |
| 978-4774182179 | [改蚂新版]Spring入門 ――Javaフレヌムワヌク・より良い蚭蚈ずアヌキテクチャ                                 |  4180 |
| 978-4797393118 | 基瀎からのMySQL 第3版 (基瀎からシリヌズ)                                                                |  6038 |
| 978-4798142470 | Spring培底入門 Spring FrameworkによるJavaアプリケヌション開発                                           |  4400 |
| 978-4798161488 | MySQL培底入門 第4版 MySQL 8.0察応                                                                       |  4180 |
+----------------+---------------------------------------------------------------------------------------------------------+-------+
6 rows in set (0.00 sec)

䞡方ずもロヌルバックしたしたが、やっぱりスタックトレヌスが倉わりたしたね。

RuntimeExceptionの堎合。

2022-05-27 01:29:24.461 DEBUG 21982 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Rollback for RuntimeException: java.lang.RuntimeException: Oops!!
2022-05-27 01:29:24.465 DEBUG 21982 --- [           main] o.s.t.support.TransactionTemplate        : Initiating transaction rollback on application exception

java.lang.RuntimeException: Oops!!
        at org.littlewings.spring.batch.BookItemProcessor.process(BookItemProcessor.java:13) ~[classes!/:0.0.1-SNAPSHOT]
        at org.littlewings.spring.batch.BookItemProcessor.process(BookItemProcessor.java:5) ~[classes!/:0.0.1-SNAPSHOT]
        at org.littlewings.spring.batch.BookItemProcessor$$FastClassBySpringCGLIB$$775ca5c7.invoke(<generated>) ~[classes!/:0.0.1-SNAPSHOT]
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.20.jar!/:5.3.20]

〜省略〜

Exceptionの堎合。

2022-05-27 01:30:48.083 DEBUG 22148 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Rollback for Exception: java.lang.Exception: Oops!!
2022-05-27 01:30:48.088 DEBUG 22148 --- [           main] o.s.t.support.TransactionTemplate        : Initiating transaction rollback on application exception

org.springframework.batch.core.step.tasklet.UncheckedTransactionException: java.lang.Exception: Oops!!
        at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:487) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:331) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140) ~[spring-tx-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:273) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:82) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:375) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:145) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:258) ~[spring-batch-core-4.3.6.jar!/:4.3.6]

〜省略〜


Caused by: java.lang.Exception: Oops!!
        at org.littlewings.spring.batch.BookItemProcessor.process(BookItemProcessor.java:14) ~[classes!/:0.0.1-SNAPSHOT]
        at org.littlewings.spring.batch.BookItemProcessor.process(BookItemProcessor.java:5) ~[classes!/:0.0.1-SNAPSHOT]
        at org.littlewings.spring.batch.BookItemProcessor$$FastClassBySpringCGLIB$$775ca5c7.invoke(<generated>) ~[classes!/:0.0.1-SNAPSHOT]
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.20.jar!/:5.3.20]

〜省略〜

ItemProcessorの堎合は、Exceptionのメッセヌゞが倉わっおおり、Exceptionによりロヌルバックしたこずになっおいたす。

2022-05-27 01:30:48.083 DEBUG 22148 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Rollback for Exception: java.lang.Exception: Oops!!
2022-05-27 01:30:48.088 DEBUG 22148 --- [           main] o.s.t.support.TransactionTemplate        : Initiating transaction rollback on application exception

org.springframework.batch.core.step.tasklet.UncheckedTransactionException: java.lang.Exception: Oops!!
        at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:487) ~[spring-batch-core-4.3.6.jar!/:4.3.6]

そしお、UncheckedTransactionExceptionをスロヌしたこずになっおいたす。

ItemProcessorが䟋倖をする堎合でも、RuntimeException、Exceptionの䞡方でロヌルバックするこずがわかりたした。

ItemProcessorは、元に戻しおおきたす。

    @Override
    public Book process(Book item) throws Exception {
        currentCount++;

        if (currentCount > 7) {
            // throw new RuntimeException("Oops!!");
            // throw new Exception("Oops!!");
        }

        return item;
    }
ItemWriterが䟋倖をスロヌする堎合

チャンクの最埌は、ItemWriterです。

RuntimeExceptionをスロヌしたす。

    @Override
    public void write(List<? extends Book> items) throws Exception {
        for (Book book : items) {
            currentCount++;

            if (currentCount > 7) {
                throw new RuntimeException("Oops!!");
                // throw new Exception("Oops!!");
            }

            entityManager.persist(book);
            entityManager.flush();
        }
    }

ログ。

2022-05-27 01:34:44.319  INFO 22497 --- [           main] o.s.b.a.b.JobLauncherApplicationRunner   : Running default command line with: []
2022-05-27 01:34:44.666  INFO 22497 --- [           main] o.s.b.c.l.support.SimpleJobLauncher      : Job: [SimpleJob: [name=chunkJob]] launched with the following parameters: [{run.id=6}]
2022-05-27 01:34:44.782  INFO 22497 --- [           main] o.s.batch.core.job.SimpleStepHandler     : Executing step: [chunkStep]
2022-05-27 01:34:44.782 DEBUG 22497 --- [           main] o.s.batch.core.step.AbstractStep         : Executing: id=6
2022-05-27 01:34:44.987 DEBUG 22497 --- [           main] o.s.b.c.step.item.ChunkOrientedTasklet   : Inputs not busy, ended: false
2022-05-27 01:34:44.988 DEBUG 22497 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Applying contribution: [StepContribution: read=3, written=3, filtered=0, readSkips=0, writeSkips=0, processSkips=0, exitStatus=EXECUTING]
2022-05-27 01:34:44.991 DEBUG 22497 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Saving step execution before commit: StepExecution: id=6, version=1, name=chunkStep, status=STARTED, exitStatus=EXECUTING, readCount=3, filterCount=0, writeCount=3 readSkipCount=0, writeSkipCount=0, processSkipCount=0, commitCount=1, rollbackCount=0, exitDescription=
2022-05-27 01:34:45.031 DEBUG 22497 --- [           main] o.s.b.c.step.item.ChunkOrientedTasklet   : Inputs not busy, ended: false
2022-05-27 01:34:45.032 DEBUG 22497 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Applying contribution: [StepContribution: read=3, written=3, filtered=0, readSkips=0, writeSkips=0, processSkips=0, exitStatus=EXECUTING]
2022-05-27 01:34:45.034 DEBUG 22497 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Saving step execution before commit: StepExecution: id=6, version=2, name=chunkStep, status=STARTED, exitStatus=EXECUTING, readCount=6, filterCount=0, writeCount=6 readSkipCount=0, writeSkipCount=0, processSkipCount=0, commitCount=2, rollbackCount=0, exitDescription=
2022-05-27 01:34:45.064 DEBUG 22497 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Applying contribution: [StepContribution: read=3, written=0, filtered=0, readSkips=0, writeSkips=0, processSkips=0, exitStatus=EXECUTING]
2022-05-27 01:34:45.064 DEBUG 22497 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Rollback for RuntimeException: java.lang.RuntimeException: Oops!!
2022-05-27 01:34:45.068 DEBUG 22497 --- [           main] o.s.t.support.TransactionTemplate        : Initiating transaction rollback on application exception

java.lang.RuntimeException: Oops!!
        at org.littlewings.spring.batch.BookItemWriter.write(BookItemWriter.java:22) ~[classes!/:0.0.1-SNAPSHOT]
        at org.littlewings.spring.batch.BookItemWriter$$FastClassBySpringCGLIB$$bd3df5e.invoke(<generated>) ~[classes!/:0.0.1-SNAPSHOT]
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:793) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:137) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.littlewings.spring.batch.BookItemWriter$$EnhancerBySpringCGLIB$$37836e73.write(<generated>) ~[classes!/:0.0.1-SNAPSHOT]
        at org.springframework.batch.core.step.item.SimpleChunkProcessor.writeItems(SimpleChunkProcessor.java:193) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.item.SimpleChunkProcessor.doWrite(SimpleChunkProcessor.java:159) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.item.SimpleChunkProcessor.write(SimpleChunkProcessor.java:294) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.item.SimpleChunkProcessor.process(SimpleChunkProcessor.java:217) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:77) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:407) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:331) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140) ~[spring-tx-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:273) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:82) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:375) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:145) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:258) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:208) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:152) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.AbstractJob.handleStep(AbstractJob.java:413) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.SimpleJob.doExecute(SimpleJob.java:136) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:320) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:149) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50) ~[spring-core-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:140) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:128) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at jdk.proxy2/jdk.proxy2.$Proxy83.run(Unknown Source) ~[na:na]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.execute(JobLauncherApplicationRunner.java:199) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.executeLocalJobs(JobLauncherApplicationRunner.java:173) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.launchJobFromProperties(JobLauncherApplicationRunner.java:160) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.run(JobLauncherApplicationRunner.java:155) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.run(JobLauncherApplicationRunner.java:150) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:762) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:752) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.littlewings.spring.batch.App.main(App.java:11) ~[classes!/:0.0.1-SNAPSHOT]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
        at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:108) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:58) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:65) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]

2022-05-27 01:34:45.113 ERROR 22497 --- [           main] o.s.batch.core.step.AbstractStep         : Encountered an error executing step chunkStep in job chunkJob

java.lang.RuntimeException: Oops!!
        at org.littlewings.spring.batch.BookItemWriter.write(BookItemWriter.java:22) ~[classes!/:0.0.1-SNAPSHOT]
        at org.littlewings.spring.batch.BookItemWriter$$FastClassBySpringCGLIB$$bd3df5e.invoke(<generated>) ~[classes!/:0.0.1-SNAPSHOT]
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:793) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:137) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.littlewings.spring.batch.BookItemWriter$$EnhancerBySpringCGLIB$$37836e73.write(<generated>) ~[classes!/:0.0.1-SNAPSHOT]
        at org.springframework.batch.core.step.item.SimpleChunkProcessor.writeItems(SimpleChunkProcessor.java:193) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.item.SimpleChunkProcessor.doWrite(SimpleChunkProcessor.java:159) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.item.SimpleChunkProcessor.write(SimpleChunkProcessor.java:294) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.item.SimpleChunkProcessor.process(SimpleChunkProcessor.java:217) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:77) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:407) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:331) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140) ~[spring-tx-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:273) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:82) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:375) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:145) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:258) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:208) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:152) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.AbstractJob.handleStep(AbstractJob.java:413) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.SimpleJob.doExecute(SimpleJob.java:136) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:320) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:149) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50) ~[spring-core-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:140) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:128) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at jdk.proxy2/jdk.proxy2.$Proxy83.run(Unknown Source) ~[na:na]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.execute(JobLauncherApplicationRunner.java:199) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.executeLocalJobs(JobLauncherApplicationRunner.java:173) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.launchJobFromProperties(JobLauncherApplicationRunner.java:160) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.run(JobLauncherApplicationRunner.java:155) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.run(JobLauncherApplicationRunner.java:150) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:762) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:752) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.littlewings.spring.batch.App.main(App.java:11) ~[classes!/:0.0.1-SNAPSHOT]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
        at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:108) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:58) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:65) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]

2022-05-27 01:34:45.118  INFO 22497 --- [           main] o.s.batch.core.step.AbstractStep         : Step: [chunkStep] executed in 334ms
2022-05-27 01:34:45.164 DEBUG 22497 --- [           main] o.s.batch.core.step.AbstractStep         : Step execution complete: StepExecution: id=6, version=4, name=chunkStep, status=FAILED, exitStatus=FAILED, readCount=9, filterCount=0, writeCount=6 readSkipCount=0, writeSkipCount=0, processSkipCount=0, commitCount=2, rollbackCount=1
2022-05-27 01:34:45.274  INFO 22497 --- [           main] o.s.b.c.l.support.SimpleJobLauncher      : Job: [SimpleJob: [name=chunkJob]] completed with the following parameters: [{run.id=6}] and the following status: [FAILED] in 470ms

ロヌルバックしおいたす。

2022-05-27 01:34:45.064 DEBUG 22497 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Rollback for RuntimeException: java.lang.RuntimeException: Oops!!
2022-05-27 01:34:45.068 DEBUG 22497 --- [           main] o.s.t.support.TransactionTemplate        : Initiating transaction rollback on application exception

java.lang.RuntimeException: Oops!!
        at org.littlewings.spring.batch.BookItemWriter.write(BookItemWriter.java:22) ~[classes!/:0.0.1-SNAPSHOT]
        at org.littlewings.spring.batch.BookItemWriter$$FastClassBySpringCGLIB$$bd3df5e.invoke(<generated>) ~[classes!/:0.0.1-SNAPSHOT]
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.20.jar!/:5.3.20]

〜省略〜

デヌタ。やはり、チャンク2぀分です。

mysql> select * from book;
+----------------+---------------------------------------------------------------------------------------------------------+-------+
| isbn           | title                                                                                                   | price |
+----------------+---------------------------------------------------------------------------------------------------------+-------+
| 978-1484237236 | The Definitive Guide to Spring Batch: Modern Finite Batch Processing in the Cloud                       |  7361 |
| 978-1492076988 | Spring Boot: Up and Running: Building Cloud Native Java and Kotlin Applications                         |  6265 |
| 978-4774182179 | [改蚂新版]Spring入門 ――Javaフレヌムワヌク・より良い蚭蚈ずアヌキテクチャ                                 |  4180 |
| 978-4797393118 | 基瀎からのMySQL 第3版 (基瀎からシリヌズ)                                                                |  6038 |
| 978-4798142470 | Spring培底入門 Spring FrameworkによるJavaアプリケヌション開発                                           |  4400 |
| 978-4798161488 | MySQL培底入門 第4版 MySQL 8.0察応                                                                       |  4180 |
+----------------+---------------------------------------------------------------------------------------------------------+-------+
6 rows in set (0.00 sec)

Exceptionをスロヌしおみたす。

    @Override
    public void write(List<? extends Book> items) throws Exception {
        for (Book book : items) {
            currentCount++;

            if (currentCount > 7) {
                // throw new RuntimeException("Oops!!");
                throw new Exception("Oops!!");
            }

            entityManager.persist(book);
            entityManager.flush();
        }
    }

ログ。

2022-05-27 01:36:02.283  INFO 22698 --- [           main] o.s.b.a.b.JobLauncherApplicationRunner   : Running default command line with: []
2022-05-27 01:36:02.598  INFO 22698 --- [           main] o.s.b.c.l.support.SimpleJobLauncher      : Job: [SimpleJob: [name=chunkJob]] launched with the following parameters: [{run.id=7}]
2022-05-27 01:36:02.715  INFO 22698 --- [           main] o.s.batch.core.job.SimpleStepHandler     : Executing step: [chunkStep]
2022-05-27 01:36:02.715 DEBUG 22698 --- [           main] o.s.batch.core.step.AbstractStep         : Executing: id=7
2022-05-27 01:36:02.920 DEBUG 22698 --- [           main] o.s.b.c.step.item.ChunkOrientedTasklet   : Inputs not busy, ended: false
2022-05-27 01:36:02.920 DEBUG 22698 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Applying contribution: [StepContribution: read=3, written=3, filtered=0, readSkips=0, writeSkips=0, processSkips=0, exitStatus=EXECUTING]
2022-05-27 01:36:02.923 DEBUG 22698 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Saving step execution before commit: StepExecution: id=7, version=1, name=chunkStep, status=STARTED, exitStatus=EXECUTING, readCount=3, filterCount=0, writeCount=3 readSkipCount=0, writeSkipCount=0, processSkipCount=0, commitCount=1, rollbackCount=0, exitDescription=
2022-05-27 01:36:02.958 DEBUG 22698 --- [           main] o.s.b.c.step.item.ChunkOrientedTasklet   : Inputs not busy, ended: false
2022-05-27 01:36:02.958 DEBUG 22698 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Applying contribution: [StepContribution: read=3, written=3, filtered=0, readSkips=0, writeSkips=0, processSkips=0, exitStatus=EXECUTING]
2022-05-27 01:36:02.960 DEBUG 22698 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Saving step execution before commit: StepExecution: id=7, version=2, name=chunkStep, status=STARTED, exitStatus=EXECUTING, readCount=6, filterCount=0, writeCount=6 readSkipCount=0, writeSkipCount=0, processSkipCount=0, commitCount=2, rollbackCount=0, exitDescription=
2022-05-27 01:36:02.990 DEBUG 22698 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Applying contribution: [StepContribution: read=3, written=0, filtered=0, readSkips=0, writeSkips=0, processSkips=0, exitStatus=EXECUTING]
2022-05-27 01:36:02.990 DEBUG 22698 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Rollback for Exception: java.lang.Exception: Oops!!
2022-05-27 01:36:02.995 DEBUG 22698 --- [           main] o.s.t.support.TransactionTemplate        : Initiating transaction rollback on application exception

org.springframework.batch.core.step.tasklet.UncheckedTransactionException: java.lang.Exception: Oops!!
        at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:487) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:331) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140) ~[spring-tx-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:273) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:82) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:375) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:145) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:258) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:208) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:152) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.AbstractJob.handleStep(AbstractJob.java:413) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.SimpleJob.doExecute(SimpleJob.java:136) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:320) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:149) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50) ~[spring-core-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:140) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:128) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at jdk.proxy2/jdk.proxy2.$Proxy83.run(Unknown Source) ~[na:na]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.execute(JobLauncherApplicationRunner.java:199) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.executeLocalJobs(JobLauncherApplicationRunner.java:173) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.launchJobFromProperties(JobLauncherApplicationRunner.java:160) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.run(JobLauncherApplicationRunner.java:155) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.run(JobLauncherApplicationRunner.java:150) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:762) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:752) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.littlewings.spring.batch.App.main(App.java:11) ~[classes!/:0.0.1-SNAPSHOT]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
        at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:108) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:58) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:65) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
Caused by: java.lang.Exception: Oops!!
        at org.littlewings.spring.batch.BookItemWriter.write(BookItemWriter.java:23) ~[classes!/:0.0.1-SNAPSHOT]
        at org.littlewings.spring.batch.BookItemWriter$$FastClassBySpringCGLIB$$bd3df5e.invoke(<generated>) ~[classes!/:0.0.1-SNAPSHOT]
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:793) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:137) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.littlewings.spring.batch.BookItemWriter$$EnhancerBySpringCGLIB$$e1ee2674.write(<generated>) ~[classes!/:0.0.1-SNAPSHOT]
        at org.springframework.batch.core.step.item.SimpleChunkProcessor.writeItems(SimpleChunkProcessor.java:193) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.item.SimpleChunkProcessor.doWrite(SimpleChunkProcessor.java:159) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.item.SimpleChunkProcessor.write(SimpleChunkProcessor.java:294) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.item.SimpleChunkProcessor.process(SimpleChunkProcessor.java:217) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:77) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:407) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        ... 46 common frames omitted

2022-05-27 01:36:03.011 ERROR 22698 --- [           main] o.s.batch.core.step.AbstractStep         : Encountered an error executing step chunkStep in job chunkJob

java.lang.Exception: Oops!!
        at org.littlewings.spring.batch.BookItemWriter.write(BookItemWriter.java:23) ~[classes!/:0.0.1-SNAPSHOT]
        at org.littlewings.spring.batch.BookItemWriter$$FastClassBySpringCGLIB$$bd3df5e.invoke(<generated>) ~[classes!/:0.0.1-SNAPSHOT]
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:793) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:137) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.littlewings.spring.batch.BookItemWriter$$EnhancerBySpringCGLIB$$e1ee2674.write(<generated>) ~[classes!/:0.0.1-SNAPSHOT]
        at org.springframework.batch.core.step.item.SimpleChunkProcessor.writeItems(SimpleChunkProcessor.java:193) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.item.SimpleChunkProcessor.doWrite(SimpleChunkProcessor.java:159) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.item.SimpleChunkProcessor.write(SimpleChunkProcessor.java:294) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.item.SimpleChunkProcessor.process(SimpleChunkProcessor.java:217) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:77) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:407) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:331) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140) ~[spring-tx-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:273) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:82) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:375) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:145) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:258) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:208) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:152) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.AbstractJob.handleStep(AbstractJob.java:413) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.SimpleJob.doExecute(SimpleJob.java:136) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:320) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:149) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50) ~[spring-core-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:140) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:128) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at jdk.proxy2/jdk.proxy2.$Proxy83.run(Unknown Source) ~[na:na]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.execute(JobLauncherApplicationRunner.java:199) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.executeLocalJobs(JobLauncherApplicationRunner.java:173) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.launchJobFromProperties(JobLauncherApplicationRunner.java:160) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.run(JobLauncherApplicationRunner.java:155) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.run(JobLauncherApplicationRunner.java:150) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:762) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:752) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.littlewings.spring.batch.App.main(App.java:11) ~[classes!/:0.0.1-SNAPSHOT]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
        at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:108) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:58) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:65) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]

2022-05-27 01:36:03.014  INFO 22698 --- [           main] o.s.batch.core.step.AbstractStep         : Step: [chunkStep] executed in 299ms
2022-05-27 01:36:03.068 DEBUG 22698 --- [           main] o.s.batch.core.step.AbstractStep         : Step execution complete: StepExecution: id=7, version=4, name=chunkStep, status=FAILED, exitStatus=FAILED, readCount=9, filterCount=0, writeCount=6 readSkipCount=0, writeSkipCount=0, processSkipCount=0, commitCount=2, rollbackCount=1
2022-05-27 01:36:03.102  INFO 22698 --- [           main] o.s.b.c.l.support.SimpleJobLauncher      : Job: [SimpleJob: [name=chunkJob]] completed with the following parameters: [{run.id=7}] and the following status: [FAILED] in 448ms

ロヌルバックしたようです。

デヌタ。

mysql> select * from book;
+----------------+---------------------------------------------------------------------------------------------------------+-------+
| isbn           | title                                                                                                   | price |
+----------------+---------------------------------------------------------------------------------------------------------+-------+
| 978-1484237236 | The Definitive Guide to Spring Batch: Modern Finite Batch Processing in the Cloud                       |  7361 |
| 978-1492076988 | Spring Boot: Up and Running: Building Cloud Native Java and Kotlin Applications                         |  6265 |
| 978-4774182179 | [改蚂新版]Spring入門 ――Javaフレヌムワヌク・より良い蚭蚈ずアヌキテクチャ                                 |  4180 |
| 978-4797393118 | 基瀎からのMySQL 第3版 (基瀎からシリヌズ)                                                                |  6038 |
| 978-4798142470 | Spring培底入門 Spring FrameworkによるJavaアプリケヌション開発                                           |  4400 |
| 978-4798161488 | MySQL培底入門 第4版 MySQL 8.0察応                                                                       |  4180 |
+----------------+---------------------------------------------------------------------------------------------------------+-------+
6 rows in set (0.00 sec)

ItemWriterの堎合は、ItemProcessorず同様にExceptionずしおロヌルバックしおいるようです。

2022-05-27 01:36:02.990 DEBUG 22698 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Rollback for Exception: java.lang.Exception: Oops!!
2022-05-27 01:36:02.995 DEBUG 22698 --- [           main] o.s.t.support.TransactionTemplate        : Initiating transaction rollback on application exception

org.springframework.batch.core.step.tasklet.UncheckedTransactionException: java.lang.Exception: Oops!!
        at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:487) ~[spring-batch-core-4.3.6.jar!/:4.3.6]

〜省略〜

UncheckedTransactionExceptionにラップされおいるのも同じようですが。

これで、ItemWriterの堎合もスロヌされる䟋倖がException、RuntimeExceptionを問わずロヌルバックされるこずがわかりたした。

ItemWriterの゜ヌスコヌドは、元に戻しおおきたす。

    @Override
    public void write(List<? extends Book> items) throws Exception {
        for (Book book : items) {
            currentCount++;

            if (currentCount > 7) {
                // throw new RuntimeException("Oops!!");
                // throw new Exception("Oops!!");
            }

            entityManager.persist(book);
            entityManager.flush();
        }
    }

Tasklet

チャンクの次は、Taskletを芋おいきたす。

Taskletの゜ヌスコヌドは、こちら。

src/main/java/org/littlewings/spring/batch/BookTasklet.java

package org.littlewings.spring.batch;

import java.util.List;
import javax.persistence.EntityManager;

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.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;

public class BookTasklet implements Tasklet {
    @Autowired
    EntityManager entityManager;

    @Override
    public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
        List<Book> books = List.of(
                Book.create("978-4798142470", "Spring培底入門 Spring FrameworkによるJavaアプリケヌション開発", 4400),
                Book.create("978-4774182179", "[改蚂新版]Spring入門 ――Javaフレヌムワヌク・より良い蚭蚈ずアヌキテクチャ", 4180),
                Book.create("978-1492076988", "Spring Boot: Up and Running: Building Cloud Native Java and Kotlin Applications", 6265),
                Book.create("978-1484237236", "The Definitive Guide to Spring Batch: Modern Finite Batch Processing in the Cloud", 7361),
                Book.create("978-4798161488", "MySQL培底入門 第4版 MySQL 8.0察応", 4180),
                Book.create("978-4797393118", "基瀎からのMySQL 第3版 (基瀎からシリヌズ)", 6038),
                Book.create("978-4873116389", "実践ハむパフォヌマンスMySQL 第3版", 5280),
                Book.create("978-4295000198", "やさしく孊べるMySQL運甚・管理入門【5.7察応】", 2860),
                Book.create("978-4798147406", "詳解MySQL 5.7 止たらぬ進化に乗り遅れないためのテクニカルガむド (NEXT ONE)", 3960),
                Book.create("978-4774170206", "MariaDB&MySQL党機胜バむブル", 3860)
        );

        int currentCount = 0;

        for (Book book : books) {
            currentCount++;

            if (currentCount > 7) {
                // throw new RuntimeException("Oops!!");
                // throw new Exception("Oops!!");
            }

            entityManager.persist(book);
            entityManager.flush();
        }

        return RepeatStatus.FINISHED;
    }
}

10件の曞籍デヌタを、1件ず぀反映したす。

Taskletもチャンクの時ず同様、7件目のデヌタを扱うずころでコメントアりトを解陀するず䟋倖をスロヌするようになっおいたす。
RuntimeExceptionおよびExceptionです。

            if (currentCount > 7) {
                // throw new RuntimeException("Oops!!");
                // throw new Exception("Oops!!");
            }

こちらもこのコメントアりトの解陀を倉化させ぀぀、どのような動きをするかを芋おいきたす。

Jobの定矩はこちら。

src/main/java/org/littlewings/spring/batch/TaskletJobConfig.java

package org.littlewings.spring.batch;

import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepScope;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class TaskletJobConfig {
    @Bean
    public Job taskletJob(JobBuilderFactory jobBuilderFactory) {
        return jobBuilderFactory
                .get("taskletJob")
                .incrementer(new RunIdIncrementer())
                .start(taskletStep(null))
                .build();
    }

    @Bean
    public Step taskletStep(StepBuilderFactory stepBuilderFactory) {
        return stepBuilderFactory
                .get("taskletStep")
                .tasklet(bookTasklet())
                .build();
    }

    @Bean
    @StepScope
    public BookTasklet bookTasklet() {
        return new BookTasklet();
    }
}

確認は、チャンクず同じように゜ヌスコヌドを倉曎し぀぀パッケヌゞングしお

$ mvn package

Jobを指定しお実行するこずにしたす。

$ java -Dspring.batch.job.names=taskletJob -jar target/batch-transaction-0.0.1-SNAPSHOT.jar
正垞に終了する堎合

たずは、正垞に終了する堎合から。

実行時のログは、こちら。

2022-05-27 01:37:47.923  INFO 22877 --- [           main] o.s.b.a.b.JobLauncherApplicationRunner   : Running default command line with: []
2022-05-27 01:37:48.192  INFO 22877 --- [           main] o.s.b.c.l.support.SimpleJobLauncher      : Job: [SimpleJob: [name=taskletJob]] launched with the following parameters: [{run.id=1}]
2022-05-27 01:37:48.373  INFO 22877 --- [           main] o.s.batch.core.job.SimpleStepHandler     : Executing step: [taskletStep]
2022-05-27 01:37:48.373 DEBUG 22877 --- [           main] o.s.batch.core.step.AbstractStep         : Executing: id=8
2022-05-27 01:37:48.543 DEBUG 22877 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Applying contribution: [StepContribution: read=0, written=0, filtered=0, readSkips=0, writeSkips=0, processSkips=0, exitStatus=EXECUTING]
2022-05-27 01:37:48.546 DEBUG 22877 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Saving step execution before commit: StepExecution: id=8, version=1, name=taskletStep, status=STARTED, exitStatus=EXECUTING, readCount=0, filterCount=0, writeCount=0 readSkipCount=0, writeSkipCount=0, processSkipCount=0, commitCount=1, rollbackCount=0, exitDescription=
2022-05-27 01:37:48.573 DEBUG 22877 --- [           main] o.s.batch.core.step.AbstractStep         : Step execution success: id=8
2022-05-27 01:37:48.582  INFO 22877 --- [           main] o.s.batch.core.step.AbstractStep         : Step: [taskletStep] executed in 208ms
2022-05-27 01:37:48.609 DEBUG 22877 --- [           main] o.s.batch.core.step.AbstractStep         : Step execution complete: StepExecution: id=8, version=3, name=taskletStep, status=COMPLETED, exitStatus=COMPLETED, readCount=0, filterCount=0, writeCount=0 readSkipCount=0, writeSkipCount=0, processSkipCount=0, commitCount=1, rollbackCount=0
2022-05-27 01:37:48.637  INFO 22877 --- [           main] o.s.b.c.l.support.SimpleJobLauncher      : Job: [SimpleJob: [name=taskletJob]] completed with the following parameters: [{run.id=1}] and the following status: [COMPLETED] in 390ms

デヌタ。

mysql> select * from book;
+----------------+---------------------------------------------------------------------------------------------------------+-------+
| isbn           | title                                                                                                   | price |
+----------------+---------------------------------------------------------------------------------------------------------+-------+
| 978-1484237236 | The Definitive Guide to Spring Batch: Modern Finite Batch Processing in the Cloud                       |  7361 |
| 978-1492076988 | Spring Boot: Up and Running: Building Cloud Native Java and Kotlin Applications                         |  6265 |
| 978-4295000198 | やさしく孊べるMySQL運甚・管理入門【5.7察応】                                                            |  2860 |
| 978-4774170206 | MariaDB&MySQL党機胜バむブル                                                                             |  3860 |
| 978-4774182179 | [改蚂新版]Spring入門 ――Javaフレヌムワヌク・より良い蚭蚈ずアヌキテクチャ                                 |  4180 |
| 978-4797393118 | 基瀎からのMySQL 第3版 (基瀎からシリヌズ)                                                                |  6038 |
| 978-4798142470 | Spring培底入門 Spring FrameworkによるJavaアプリケヌション開発                                           |  4400 |
| 978-4798147406 | 詳解MySQL 5.7 止たらぬ進化に乗り遅れないためのテクニカルガむド (NEXT ONE)                               |  3960 |
| 978-4798161488 | MySQL培底入門 第4版 MySQL 8.0察応                                                                       |  4180 |
| 978-4873116389 | 実践ハむパフォヌマンスMySQL 第3版                                                                       |  5280 |
+----------------+---------------------------------------------------------------------------------------------------------+-------+
10 rows in set (0.00 sec)
Taskletが䟋倖をスロヌする堎合

では、䟋倖をスロヌするようにしお動䜜確認しおみたす。

たずはRuntimeExceptionをスロヌしおみたす。

        for (Book book : books) {
            currentCount++;

            if (currentCount > 7) {
                throw new RuntimeException("Oops!!");
                // throw new Exception("Oops!!");
            }

            entityManager.persist(book);
            entityManager.flush();
        }

ログ。

2022-05-27 01:39:52.695  INFO 23081 --- [           main] o.s.b.a.b.JobLauncherApplicationRunner   : Running default command line with: []
2022-05-27 01:39:53.006  INFO 23081 --- [           main] o.s.b.c.l.support.SimpleJobLauncher      : Job: [SimpleJob: [name=taskletJob]] launched with the following parameters: [{run.id=2}]
2022-05-27 01:39:53.140  INFO 23081 --- [           main] o.s.batch.core.job.SimpleStepHandler     : Executing step: [taskletStep]
2022-05-27 01:39:53.140 DEBUG 23081 --- [           main] o.s.batch.core.step.AbstractStep         : Executing: id=9
2022-05-27 01:39:53.320 DEBUG 23081 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Applying contribution: [StepContribution: read=0, written=0, filtered=0, readSkips=0, writeSkips=0, processSkips=0, exitStatus=EXECUTING]
2022-05-27 01:39:53.320 DEBUG 23081 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Rollback for RuntimeException: java.lang.RuntimeException: Oops!!
2022-05-27 01:39:53.326 DEBUG 23081 --- [           main] o.s.t.support.TransactionTemplate        : Initiating transaction rollback on application exception

java.lang.RuntimeException: Oops!!
        at org.littlewings.spring.batch.BookTasklet.execute(BookTasklet.java:37) ~[classes!/:0.0.1-SNAPSHOT]
        at org.littlewings.spring.batch.BookTasklet$$FastClassBySpringCGLIB$$1150977e.invoke(<generated>) ~[classes!/:0.0.1-SNAPSHOT]
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:793) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:137) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.littlewings.spring.batch.BookTasklet$$EnhancerBySpringCGLIB$$54aa2694.execute(<generated>) ~[classes!/:0.0.1-SNAPSHOT]
        at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:407) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:331) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140) ~[spring-tx-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:273) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:82) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:375) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:145) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:258) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:208) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:152) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.AbstractJob.handleStep(AbstractJob.java:413) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.SimpleJob.doExecute(SimpleJob.java:136) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:320) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:149) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50) ~[spring-core-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:140) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:128) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at jdk.proxy2/jdk.proxy2.$Proxy83.run(Unknown Source) ~[na:na]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.execute(JobLauncherApplicationRunner.java:199) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.executeLocalJobs(JobLauncherApplicationRunner.java:173) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.launchJobFromProperties(JobLauncherApplicationRunner.java:160) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.run(JobLauncherApplicationRunner.java:155) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.run(JobLauncherApplicationRunner.java:150) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:762) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:752) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.littlewings.spring.batch.App.main(App.java:11) ~[classes!/:0.0.1-SNAPSHOT]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
        at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:108) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:58) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:65) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]

2022-05-27 01:39:53.363 ERROR 23081 --- [           main] o.s.batch.core.step.AbstractStep         : Encountered an error executing step taskletStep in job taskletJob

java.lang.RuntimeException: Oops!!
        at org.littlewings.spring.batch.BookTasklet.execute(BookTasklet.java:37) ~[classes!/:0.0.1-SNAPSHOT]
        at org.littlewings.spring.batch.BookTasklet$$FastClassBySpringCGLIB$$1150977e.invoke(<generated>) ~[classes!/:0.0.1-SNAPSHOT]
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:793) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:137) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.littlewings.spring.batch.BookTasklet$$EnhancerBySpringCGLIB$$54aa2694.execute(<generated>) ~[classes!/:0.0.1-SNAPSHOT]
        at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:407) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:331) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140) ~[spring-tx-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:273) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:82) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:375) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:145) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:258) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:208) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:152) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.AbstractJob.handleStep(AbstractJob.java:413) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.SimpleJob.doExecute(SimpleJob.java:136) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:320) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:149) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50) ~[spring-core-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:140) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:128) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at jdk.proxy2/jdk.proxy2.$Proxy83.run(Unknown Source) ~[na:na]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.execute(JobLauncherApplicationRunner.java:199) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.executeLocalJobs(JobLauncherApplicationRunner.java:173) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.launchJobFromProperties(JobLauncherApplicationRunner.java:160) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.run(JobLauncherApplicationRunner.java:155) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.run(JobLauncherApplicationRunner.java:150) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:762) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:752) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.littlewings.spring.batch.App.main(App.java:11) ~[classes!/:0.0.1-SNAPSHOT]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
        at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:108) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:58) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:65) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]

2022-05-27 01:39:53.369  INFO 23081 --- [           main] o.s.batch.core.step.AbstractStep         : Step: [taskletStep] executed in 229ms
2022-05-27 01:39:53.410 DEBUG 23081 --- [           main] o.s.batch.core.step.AbstractStep         : Step execution complete: StepExecution: id=9, version=2, name=taskletStep, status=FAILED, exitStatus=FAILED, readCount=0, filterCount=0, writeCount=0 readSkipCount=0, writeSkipCount=0, processSkipCount=0, commitCount=0, rollbackCount=1
2022-05-27 01:39:53.441  INFO 23081 --- [           main] o.s.b.c.l.support.SimpleJobLauncher      : Job: [SimpleJob: [name=taskletJob]] completed with the following parameters: [{run.id=2}] and the following status: [FAILED] in 384ms

ロヌルバックしおいたす。

2022-05-27 01:39:53.320 DEBUG 23081 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Rollback for RuntimeException: java.lang.RuntimeException: Oops!!
2022-05-27 01:39:53.326 DEBUG 23081 --- [           main] o.s.t.support.TransactionTemplate        : Initiating transaction rollback on application exception

java.lang.RuntimeException: Oops!!
        at org.littlewings.spring.batch.BookTasklet.execute(BookTasklet.java:37) ~[classes!/:0.0.1-SNAPSHOT]
        at org.littlewings.spring.batch.BookTasklet$$FastClassBySpringCGLIB$$1150977e.invoke(<generated>) ~[classes!/:0.0.1-SNAPSHOT]

〜省略〜

Taskletの堎合はトランザクションはひず぀なので、すべおのデヌタがロヌルバックしたしたね。

mysql> select * from book;
Empty set (0.00 sec)

Exceptionをスロヌしおみたす。

        for (Book book : books) {
            currentCount++;

            if (currentCount > 7) {
                // throw new RuntimeException("Oops!!");
                throw new Exception("Oops!!");
            }

            entityManager.persist(book);
            entityManager.flush();
        }

ログ。

2022-05-27 01:41:41.628  INFO 23266 --- [           main] o.s.b.a.b.JobLauncherApplicationRunner   : Running default command line with: []
2022-05-27 01:41:41.962  INFO 23266 --- [           main] o.s.b.c.l.support.SimpleJobLauncher      : Job: [SimpleJob: [name=taskletJob]] launched with the following parameters: [{run.id=3}]
2022-05-27 01:41:42.092  INFO 23266 --- [           main] o.s.batch.core.job.SimpleStepHandler     : Executing step: [taskletStep]
2022-05-27 01:41:42.093 DEBUG 23266 --- [           main] o.s.batch.core.step.AbstractStep         : Executing: id=10
2022-05-27 01:41:42.254 DEBUG 23266 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Applying contribution: [StepContribution: read=0, written=0, filtered=0, readSkips=0, writeSkips=0, processSkips=0, exitStatus=EXECUTING]
2022-05-27 01:41:42.255 DEBUG 23266 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Rollback for Exception: java.lang.Exception: Oops!!
2022-05-27 01:41:42.260 DEBUG 23266 --- [           main] o.s.t.support.TransactionTemplate        : Initiating transaction rollback on application exception

org.springframework.batch.core.step.tasklet.UncheckedTransactionException: java.lang.Exception: Oops!!
        at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:487) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:331) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140) ~[spring-tx-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:273) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:82) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:375) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:145) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:258) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:208) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:152) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.AbstractJob.handleStep(AbstractJob.java:413) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.SimpleJob.doExecute(SimpleJob.java:136) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:320) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:149) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50) ~[spring-core-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:140) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:128) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at jdk.proxy2/jdk.proxy2.$Proxy83.run(Unknown Source) ~[na:na]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.execute(JobLauncherApplicationRunner.java:199) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.executeLocalJobs(JobLauncherApplicationRunner.java:173) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.launchJobFromProperties(JobLauncherApplicationRunner.java:160) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.run(JobLauncherApplicationRunner.java:155) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.run(JobLauncherApplicationRunner.java:150) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:762) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:752) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.littlewings.spring.batch.App.main(App.java:11) ~[classes!/:0.0.1-SNAPSHOT]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
        at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:108) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:58) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:65) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
Caused by: java.lang.Exception: Oops!!
        at org.littlewings.spring.batch.BookTasklet.execute(BookTasklet.java:38) ~[classes!/:0.0.1-SNAPSHOT]
        at org.littlewings.spring.batch.BookTasklet$$FastClassBySpringCGLIB$$1150977e.invoke(<generated>) ~[classes!/:0.0.1-SNAPSHOT]
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:793) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:137) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.littlewings.spring.batch.BookTasklet$$EnhancerBySpringCGLIB$$54aa2694.execute(<generated>) ~[classes!/:0.0.1-SNAPSHOT]
        at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:407) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        ... 46 common frames omitted

2022-05-27 01:41:42.288 ERROR 23266 --- [           main] o.s.batch.core.step.AbstractStep         : Encountered an error executing step taskletStep in job taskletJob

java.lang.Exception: Oops!!
        at org.littlewings.spring.batch.BookTasklet.execute(BookTasklet.java:38) ~[classes!/:0.0.1-SNAPSHOT]
        at org.littlewings.spring.batch.BookTasklet$$FastClassBySpringCGLIB$$1150977e.invoke(<generated>) ~[classes!/:0.0.1-SNAPSHOT]
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:793) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:137) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.littlewings.spring.batch.BookTasklet$$EnhancerBySpringCGLIB$$54aa2694.execute(<generated>) ~[classes!/:0.0.1-SNAPSHOT]
        at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:407) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:331) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140) ~[spring-tx-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:273) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:82) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:375) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:145) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:258) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:208) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:152) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.AbstractJob.handleStep(AbstractJob.java:413) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.SimpleJob.doExecute(SimpleJob.java:136) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:320) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:149) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50) ~[spring-core-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:140) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:128) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215) ~[spring-aop-5.3.20.jar!/:5.3.20]
        at jdk.proxy2/jdk.proxy2.$Proxy83.run(Unknown Source) ~[na:na]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.execute(JobLauncherApplicationRunner.java:199) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.executeLocalJobs(JobLauncherApplicationRunner.java:173) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.launchJobFromProperties(JobLauncherApplicationRunner.java:160) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.run(JobLauncherApplicationRunner.java:155) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.run(JobLauncherApplicationRunner.java:150) ~[spring-boot-autoconfigure-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:762) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:752) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) ~[spring-boot-2.7.0.jar!/:2.7.0]
        at org.littlewings.spring.batch.App.main(App.java:11) ~[classes!/:0.0.1-SNAPSHOT]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
        at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:108) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:58) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:65) ~[batch-transaction-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]

2022-05-27 01:41:42.297  INFO 23266 --- [           main] o.s.batch.core.step.AbstractStep         : Step: [taskletStep] executed in 203ms
2022-05-27 01:41:42.362 DEBUG 23266 --- [           main] o.s.batch.core.step.AbstractStep         : Step execution complete: StepExecution: id=10, version=2, name=taskletStep, status=FAILED, exitStatus=FAILED, readCount=0, filterCount=0, writeCount=0 readSkipCount=0, writeSkipCount=0, processSkipCount=0, commitCount=0, rollbackCount=1
2022-05-27 01:41:42.411  INFO 23266 --- [           main] o.s.b.c.l.support.SimpleJobLauncher      : Job: [SimpleJob: [name=taskletJob]] completed with the following parameters: [{run.id=3}] and the following status: [FAILED] in 377ms

ロヌルバックしたした。

2022-05-27 01:41:42.260 DEBUG 23266 --- [           main] o.s.t.support.TransactionTemplate        : Initiating transaction rollback on application exception

org.springframework.batch.core.step.tasklet.UncheckedTransactionException: java.lang.Exception: Oops!!
        at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:487) ~[spring-batch-core-4.3.6.jar!/:4.3.6]

〜省略〜

チャンクの時ず同じように、UncheckedTransactionExceptionにラップされおスロヌされおいたすね。ロヌルバックの理由に぀いおは
Exceptionずしお扱っおいたすが。

デヌタもロヌルバックされおいたす。

mysql> select * from book;
Empty set (0.00 sec)

RuntimeExceptionずExceptionのスタックトレヌスをちょっず比范。

RuntimeException。

2022-05-27 01:39:53.320 DEBUG 23081 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Rollback for RuntimeException: java.lang.RuntimeException: Oops!!
2022-05-27 01:39:53.326 DEBUG 23081 --- [           main] o.s.t.support.TransactionTemplate        : Initiating transaction rollback on application exception

java.lang.RuntimeException: Oops!!
        at org.littlewings.spring.batch.BookTasklet.execute(BookTasklet.java:37) ~[classes!/:0.0.1-SNAPSHOT]
        at org.littlewings.spring.batch.BookTasklet$$FastClassBySpringCGLIB$$1150977e.invoke(<generated>) ~[classes!/:0.0.1-SNAPSHOT]
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.20.jar!/:5.3.20]

〜省略〜

Exception。

2022-05-27 01:41:42.255 DEBUG 23266 --- [           main] o.s.batch.core.step.tasklet.TaskletStep  : Rollback for Exception: java.lang.Exception: Oops!!
2022-05-27 01:41:42.260 DEBUG 23266 --- [           main] o.s.t.support.TransactionTemplate        : Initiating transaction rollback on application exception

org.springframework.batch.core.step.tasklet.UncheckedTransactionException: java.lang.Exception: Oops!!
        at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:487) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:331) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140) ~[spring-tx-5.3.20.jar!/:5.3.20]
        at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:273) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:82) ~[spring-batch-core-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:375) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:145) ~[spring-batch-infrastructure-4.3.6.jar!/:4.3.6]
        at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:258) ~[spring-batch-core-4.3.6.jar!/:4.3.6]

〜省略〜

Caused by: java.lang.Exception: Oops!!
        at org.littlewings.spring.batch.BookTasklet.execute(BookTasklet.java:38) ~[classes!/:0.0.1-SNAPSHOT]
        at org.littlewings.spring.batch.BookTasklet$$FastClassBySpringCGLIB$$1150977e.invoke(<generated>) ~[classes!/:0.0.1-SNAPSHOT]
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.20.jar!/:5.3.20]

〜省略〜

これで、Taskletの堎合もスロヌされる䟋倖がRuntimeExceptionであっおもExceptionであっおもロヌルバックされるこずがわかりたしたね。

゜ヌスコヌドは、元に戻しおおきたす。

        for (Book book : books) {
            currentCount++;

            if (currentCount > 7) {
                // throw new RuntimeException("Oops!!");
                // throw new Exception("Oops!!");
            }

            entityManager.persist(book);
            entityManager.flush();
        }

少し远っおみる

ここたで芋おきお、各芁玠からExceptionがスロヌされた堎合は、RepeatExceptionたたはUncheckedTransactionExceptionにラップされお
再床スロヌされるこずがわかりたした。

たた、この時のItemProcessor、ItemWriter、Taskletのスタックトレヌスはすべお同じであり、ラップされる䟋倖も
UncheckedTransactionExceptionです。ItemReaderだけ異なり、ラップされる䟋倖はRepeatExceptionですね。

ここで少し、Spring Batchの実装を芋おみたしょう。

ItemReaderで䟋倖を扱っおいた再スロヌしおいたのは、こちらでした。

https://github.com/spring-projects/spring-batch/blob/4.3.6/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/RepeatTemplate.java#L312-L322

Error、RuntimeException、Exceptionそれぞれを芋おいたす。Exceptionの堎合は、RepeatExceptionずいう䟋倖でラップしお
再スロヌですね。

ItemProcessor、ItemWriter、Taskletの堎合はこちら。

https://github.com/spring-projects/spring-batch/blob/4.3.6/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/TaskletStep.java#L467-L488

Error、RuntimeException、Exceptionそれぞれを芋おいたす。Exceptionの堎合は、UncheckedTransactionExceptionずいう
䟋倖にラップされおスロヌされたす。

https://github.com/spring-projects/spring-batch/blob/4.3.6/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/TaskletStep.java#L487

https://github.com/spring-projects/spring-batch/blob/4.3.6/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/TaskletStep.java#L277

そしお、いずれの構成芁玠であっおも、RuntimeException、Exception問わず、䟋倖がスロヌされたらロヌルバックされるこずが
確認できたした、ず。

たずめ

Spring Batchのトランザクション管理で、スロヌされる䟋倖がRuntimeException、Exceptionに関わらずロヌルバックされるこずを
確認しおみたした。

なんずなくExceptionでもロヌルバックするのだろうず思っおいたしたが、実際に確認しおおくず安心かなず。

Exceptionの堎合は、内郚的には別の䟋倖でラップされお再スロヌされおいるこずもわかりたしたし。