SonarQube の Java Rule S2229 を検証する

目的

  • 未公開記事の発掘
  • 3回くらい「動かないんですけど」と相談されたから機械的にチェックしたくて調べてたやつらしい

あるメソッドから同じクラスのメソッドを呼び出すとき、 @Transactionalpropagation 属性に指定した値に間違った組み合わせがあると実行時エラーになる、という問題を警告するルールらしい。

しかし、動かしてみても実行時エラーにはなりませんでした。

いろいろな組み合わせを確認してみた結果は次のとおり。

  • トランザクションを宣言せずに Spring Data JPAリポジトリにアクセスする
  • @Transaction なしのメソッドから @Transaction ありのメソッドにアクセスする
    • 呼び出し先の @Transaction の記述が無視されている
      • require, nested, reuquires_new
    • おそらく Spring Data JPA が介入して Spring Data JPAリポジトリにアクセスに対応するトランザクションが開始する
  • @Transaction ありのメソッドから @Transaction ありのメソッドにアクセスする
    • 呼び出し元の @Transaction に対応するトランザクションは開始している
    • 呼び出し先の @Transaction の記述が無視されている
      • require, nested, reuquires_new

実行時エラーにはなりませんでしたが、呼び出し先の @Transaction の記述は無視されるようです。 NESTED などトランザクション範囲を制御するつもりで使っている場合はちゃんと制御できているか確かめたほうがいいでしょう。

サンプルコードはこちら

@Transaction なしのメソッドから

propagation=NESTED のメソッドを呼び出した場合

DEBUG 5752 o.s.orm.jpa.JpaTransactionManager: Creating new transaction with name [o.s.d.j.r.s.SimpleJpaRepository.deleteAll]: \
  PROPAGATION_REQUIRED,ISOLATION_DEFAULT
DEBUG 5752 o.s.orm.jpa.JpaTransactionManager: Creating new transaction with name [o.s.d.j.r.s.SimpleJpaRepository.save]: \
  PROPAGATION_REQUIRED,ISOLATION_DEFAULT
DEBUG 5752 o.s.orm.jpa.JpaTransactionManager: Creating new transaction with name [o.s.d.j.r.s.SimpleJpaRepository.findAll]: \
  PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly
DEBUG 5752 o.s.orm.jpa.JpaTransactionManager: Creating new transaction with name [o.s.d.j.r.s.SimpleJpaRepository.save]: \
  PROPAGATION_REQUIRED,ISOLATION_DEFAULT
DEBUG 5752 o.s.orm.jpa.JpaTransactionManager: Creating new transaction with name [o.s.d.j.r.s.SimpleJpaRepository.findAll]: \
  PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly

propagation=REQUIRED のメソッドを呼び出した場合

DEBUG 5752 o.s.orm.jpa.JpaTransactionManager: Creating new transaction with name [o.s.d.j.r.s.SimpleJpaRepository.deleteAll]: \
  PROPAGATION_REQUIRED,ISOLATION_DEFAULT
DEBUG 5752 o.s.orm.jpa.JpaTransactionManager: Creating new transaction with name [o.s.d.j.r.s.SimpleJpaRepository.save]: \
  PROPAGATION_REQUIRED,ISOLATION_DEFAULT
DEBUG 5752 o.s.orm.jpa.JpaTransactionManager: Creating new transaction with name [o.s.d.j.r.s.SimpleJpaRepository.findAll]: \
  PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly
DEBUG 5752 o.s.orm.jpa.JpaTransactionManager: Creating new transaction with name [o.s.d.j.r.s.SimpleJpaRepository.save]: \
  PROPAGATION_REQUIRED,ISOLATION_DEFAULT
DEBUG 5752 o.s.orm.jpa.JpaTransactionManager: Creating new transaction with name [o.s.d.j.r.s.SimpleJpaRepository.findAll]: \
  PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly

propagation=REQUIRE_NEW のメソッドを呼び出した場合

DEBUG 5752 o.s.orm.jpa.JpaTransactionManager: Creating new transaction with name [o.s.d.j.r.s.SimpleJpaRepository.deleteAll]: \
  PROPAGATION_REQUIRED,ISOLATION_DEFAULT
DEBUG 5752 o.s.orm.jpa.JpaTransactionManager: Creating new transaction with name [o.s.d.j.r.s.SimpleJpaRepository.save]: \
  PROPAGATION_REQUIRED,ISOLATION_DEFAULT
DEBUG 5752 o.s.orm.jpa.JpaTransactionManager: Creating new transaction with name [o.s.d.j.r.s.SimpleJpaRepository.findAll]: \
  PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly
DEBUG 5752 o.s.orm.jpa.JpaTransactionManager: Creating new transaction with name [o.s.d.j.r.s.SimpleJpaRepository.save]: \
  PROPAGATION_REQUIRED,ISOLATION_DEFAULT
DEBUG 5752 o.s.orm.jpa.JpaTransactionManager: Creating new transaction with name [o.s.d.j.r.s.SimpleJpaRepository.findAll]: \
  PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly

propagation=NESTED のメソッドから

@Transaction なしのメソッドを呼び出した場合

DEBUG 5752 o.s.orm.jpa.JpaTransactionManager: Creating new transaction with name [o.s.d.j.r.s.SimpleJpaRepository.deleteAll]: \
  PROPAGATION_REQUIRED,ISOLATION_DEFAULT
DEBUG 5752 o.s.orm.jpa.JpaTransactionManager: Creating new transaction with name [o.s.d.j.r.s.SimpleJpaRepository.save]: \
  PROPAGATION_REQUIRED,ISOLATION_DEFAULT
DEBUG 5752 o.s.orm.jpa.JpaTransactionManager: Creating new transaction with name [o.b.y.t.i.ExampleServiceImpl.nestedEmpty]: \
  PROPAGATION_NESTED,ISOLATION_DEFAULT

propagation=REQUIRED のメソッドを呼び出した場合

DEBUG 5752 o.s.orm.jpa.JpaTransactionManager: Creating new transaction with name [o.s.d.j.r.s.SimpleJpaRepository.deleteAll]: \
  PROPAGATION_REQUIRED,ISOLATION_DEFAULT
DEBUG 5752 o.s.orm.jpa.JpaTransactionManager: Creating new transaction with name [o.s.d.j.r.s.SimpleJpaRepository.save]: \
  PROPAGATION_REQUIRED,ISOLATION_DEFAULT
DEBUG 5752 o.s.orm.jpa.JpaTransactionManager: Creating new transaction with name [o.b.y.t.i.ExampleServiceImpl.nestedRequire]: \
  PROPAGATION_NESTED,ISOLATION_DEFAULT

propagation=REQUIRE_NEW のメソッドを呼び出した場合

DEBUG 5752 o.s.orm.jpa.JpaTransactionManager: Creating new transaction with name [o.s.d.j.r.s.SimpleJpaRepository.deleteAll]: \
  PROPAGATION_REQUIRED,ISOLATION_DEFAULT
DEBUG 5752 o.s.orm.jpa.JpaTransactionManager: Creating new transaction with name [o.s.d.j.r.s.SimpleJpaRepository.save]: \
  PROPAGATION_REQUIRED,ISOLATION_DEFAULT
DEBUG 5752 o.s.orm.jpa.JpaTransactionManager: Creating new transaction with name [o.b.y.t.i.ExampleServiceImpl.nestedRequireNew]: \
  PROPAGATION_NESTED,ISOLATION_DEFAULT

propagation=REQUIRED のメソッドから

@Transaction なしのメソッドを呼び出した場合

2020-09-03 16:41:49.794 DEBUG 5752 --- [           main] o.s.orm.jpa.JpaTransactionManager        : Creating new transaction with name [org.springframework.data.jpa.repository.support.SimpleJpaRepository.deleteAll]: \
  PROPAGATION_REQUIRED,ISOLATION_DEFAULT
2020-09-03 16:41:49.801 DEBUG 5752 --- [           main] o.s.orm.jpa.JpaTransactionManager        : Creating new transaction with name [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]: \
  PROPAGATION_REQUIRED,ISOLATION_DEFAULT
2020-09-03 16:41:49.807 DEBUG 5752 --- [           main] o.s.orm.jpa.JpaTransactionManager        : Creating new transaction with name [org.bitbucket.yujiorama.transactionfromsameclass.impl.ExampleServiceImpl.requireEmpty]: \
  PROPAGATION_REQUIRED,ISOLATION_DEFAULT

propagation=NESTED のメソッドを呼び出した場合

2020-09-03 16:41:49.911 DEBUG 5752 --- [           main] o.s.orm.jpa.JpaTransactionManager        : Creating new transaction with name [org.springframework.data.jpa.repository.support.SimpleJpaRepository.deleteAll]: \
  PROPAGATION_REQUIRED,ISOLATION_DEFAULT
2020-09-03 16:41:49.923 DEBUG 5752 --- [           main] o.s.orm.jpa.JpaTransactionManager        : Creating new transaction with name [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]: \
  PROPAGATION_REQUIRED,ISOLATION_DEFAULT
2020-09-03 16:41:49.937 DEBUG 5752 --- [           main] o.s.orm.jpa.JpaTransactionManager        : Creating new transaction with name [org.bitbucket.yujiorama.transactionfromsameclass.impl.ExampleServiceImpl.requireNested]: \
  PROPAGATION_REQUIRED,ISOLATION_DEFAULT

propagation=REQUIRE_NEW のメソッドを呼び出した場合

2020-09-03 16:41:50.050 DEBUG 5752 --- [           main] o.s.orm.jpa.JpaTransactionManager        : Creating new transaction with name [org.springframework.data.jpa.repository.support.SimpleJpaRepository.deleteAll]: \
  PROPAGATION_REQUIRED,ISOLATION_DEFAULT
2020-09-03 16:41:50.070 DEBUG 5752 --- [           main] o.s.orm.jpa.JpaTransactionManager        : Creating new transaction with name [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]: \
  PROPAGATION_REQUIRED,ISOLATION_DEFAULT
2020-09-03 16:41:50.077 DEBUG 5752 --- [           main] o.s.orm.jpa.JpaTransactionManager        : Creating new transaction with name [org.bitbucket.yujiorama.transactionfromsameclass.impl.ExampleServiceImpl.requireRequireNew]: \
  PROPAGATION_REQUIRED,ISOLATION_DEFAULT

propagation=REQUIRES_NEW のメソッドから

@Transaction なしのメソッドを呼び出した場合

2020-09-03 16:41:49.693 DEBUG 5752 --- [           main] o.s.orm.jpa.JpaTransactionManager        : Creating new transaction with name [org.springframework.data.jpa.repository.support.SimpleJpaRepository.deleteAll]: \
  PROPAGATION_REQUIRED,ISOLATION_DEFAULT
2020-09-03 16:41:49.733 DEBUG 5752 --- [           main] o.s.orm.jpa.JpaTransactionManager        : Creating new transaction with name [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]: \
  PROPAGATION_REQUIRED,ISOLATION_DEFAULT
2020-09-03 16:41:49.739 DEBUG 5752 --- [           main] o.s.orm.jpa.JpaTransactionManager        : Creating new transaction with name [org.bitbucket.yujiorama.transactionfromsameclass.impl.ExampleServiceImpl.requireNewEmpty]: \
  PROPAGATION_REQUIRES_NEW,ISOLATION_DEFAULT

propagation=NESTED のメソッドを呼び出した場合

2020-09-03 16:41:49.845 DEBUG 5752 --- [           main] o.s.orm.jpa.JpaTransactionManager        : Creating new transaction with name [org.springframework.data.jpa.repository.support.SimpleJpaRepository.deleteAll]: \
  PROPAGATION_REQUIRED,ISOLATION_DEFAULT
2020-09-03 16:41:49.852 DEBUG 5752 --- [           main] o.s.orm.jpa.JpaTransactionManager        : Creating new transaction with name [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]: \
  PROPAGATION_REQUIRED,ISOLATION_DEFAULT
2020-09-03 16:41:49.857 DEBUG 5752 --- [           main] o.s.orm.jpa.JpaTransactionManager        : Creating new transaction with name [org.bitbucket.yujiorama.transactionfromsameclass.impl.ExampleServiceImpl.requireNewNested]: \
  PROPAGATION_REQUIRES_NEW,ISOLATION_DEFAULT

propagation=REQUIRED のメソッドを呼び出した場合

2020-09-03 16:41:49.815 DEBUG 5752 --- [           main] o.s.orm.jpa.JpaTransactionManager        : Creating new transaction with name [org.springframework.data.jpa.repository.support.SimpleJpaRepository.deleteAll]: \
  PROPAGATION_REQUIRED,ISOLATION_DEFAULT
2020-09-03 16:41:49.822 DEBUG 5752 --- [           main] o.s.orm.jpa.JpaTransactionManager        : Creating new transaction with name [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]: \
  PROPAGATION_REQUIRED,ISOLATION_DEFAULT
2020-09-03 16:41:49.829 DEBUG 5752 --- [           main] o.s.orm.jpa.JpaTransactionManager        : Creating new transaction with name [org.bitbucket.yujiorama.transactionfromsameclass.impl.ExampleServiceImpl.requireNewRequire]: \
  PROPAGATION_REQUIRES_NEW,ISOLATION_DEFAULT