Spring Boot で @sql の executionPhase にハマった

# はじめに
Spring Boot でUnitテストを書いていた際に、executionPhase を使ってハマったことを残します。

# バージョン
Spring Boot 3.4.2

# ハマったこと
```java
@Sql(executionPhase = ExecutionPhase.BEFORE_TEST_CLASS)
```
を付けたらトランザクションがコミットされることに気づかなかった。

# 経緯
クラスに`@Sql`を書けば１回だけデータ投入され、各UTケース（メソッド）で利用できるかな、と思っていました。

動かしてみると、各ケースごとに`@Sql`のデータ投入が動いていることに気づきました。

`org.springframework.jdbc.datasource.init` のログレベルをDEBUGにして実行結果を確認。

```
logging:
  level:
    '[org.springframework.jdbc.datasource.init]': DEBUG
```


```java
@SpringBootTest
@Transactional
@Sql
public class DemoTest {

	@Test
	void test1() {
		System.out.println("test1");
	}

	@Test
	void test2() {
		System.out.println("test2");
	}

}

```
2回、`@Sql`のSQL（DemoTest.sql）が実行されています。
```
2025-02-02T12:50:30.509+09:00 DEBUG 3664 --- [spring-boot-ut] [           main] o.s.jdbc.datasource.init.ScriptUtils     : Executing SQL script from class path resource [com/example/demo/DemoTest.sql]
2025-02-02T12:50:30.540+09:00 DEBUG 3664 --- [spring-boot-ut] [           main] o.s.jdbc.datasource.init.ScriptUtils     : 0 returned as update count for SQL: CREATE TABLE IF NOT EXISTS m_class ( id INT auto_increment PRIMARY KEY, name VARCHAR(50) )
2025-02-02T12:50:30.549+09:00 DEBUG 3664 --- [spring-boot-ut] [           main] o.s.jdbc.datasource.init.ScriptUtils     : 1 returned as update count for SQL: INSERT INTO m_class(name) VALUES('DemoTest')
2025-02-02T12:50:30.551+09:00 DEBUG 3664 --- [spring-boot-ut] [           main] o.s.jdbc.datasource.init.ScriptUtils     : Executed SQL script from class path resource [com/example/demo/DemoTest.sql] in 40 ms.

～～ 中略 ～～

2025-02-02T12:50:31.354+09:00 DEBUG 3664 --- [spring-boot-ut] [           main] o.s.jdbc.datasource.init.ScriptUtils     : Executing SQL script from class path resource [com/example/demo/DemoTest.sql]
2025-02-02T12:50:31.354+09:00 DEBUG 3664 --- [spring-boot-ut] [           main] o.s.jdbc.datasource.init.ScriptUtils     : 0 returned as update count for SQL: CREATE TABLE IF NOT EXISTS m_class ( id INT auto_increment PRIMARY KEY, name VARCHAR(50) )
2025-02-02T12:50:31.355+09:00 DEBUG 3664 --- [spring-boot-ut] [           main] o.s.jdbc.datasource.init.ScriptUtils     : 1 returned as update count for SQL: INSERT INTO m_class(name) VALUES('DemoTest')
2025-02-02T12:50:31.355+09:00 DEBUG 3664 --- [spring-boot-ut] [           main] o.s.jdbc.datasource.init.ScriptUtils     : Executed SQL script from class path resource [com/example/demo/DemoTest.sql] in 1 ms.

```

どうせなら１回だけいいかな？と思い、以下を発見。付与してみたら１回だけに変わりました。

```java
@Sql(executionPhase = ExecutionPhase.BEFORE_TEST_CLASS)
```

が！トランザクションがコミットされるようになってしまいました。

`org.springframework.jdbc.support.JdbcTransactionManager` のログレベルをDEBUGにして確認。

```
logging:
  level:
    '[org.springframework.jdbc.datasource.init]': DEBUG
    '[org.springframework.jdbc.support.JdbcTransactionManager]': DEBUG
```

```
2025-02-02T13:01:33.027+09:00 DEBUG 16396 --- [spring-boot-ut] [           main] o.s.jdbc.support.JdbcTransactionManager  : Initiating transaction commit
```

UTが複数クラスあると、1個目のUTクラスの`@Sql`のデータが残り、2個目のUTクラスの実行時に意図しない動きをしてしまいました。

加えてUTクラス単位でデータが繋がってしまうのはよくない。と。

# 結果
`ExecutionPhase.BEFORE_TEST_CLASS` をやめて、ケース（メソッド）毎実行する方法に戻しました。

# サンプルソース
https://github.com/tarosuke777/spring-boot-ut-sql-executionPhase