From 62292f7fb480fe3feb069bd30dd56828a6131696 Mon Sep 17 00:00:00 2001 From: hong-sile Date: Tue, 10 Oct 2023 13:34:01 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=ED=8A=B8=EB=9E=9C=EC=9E=AD=EC=85=98?= =?UTF-8?q?=EC=9D=B4=20=ED=99=9C=EC=84=B1=ED=99=94=20=EC=97=AC=EB=B6=80?= =?UTF-8?q?=EC=97=90=20=EB=94=B0=EB=9D=BC=20Connection=EC=9D=84=20close=20?= =?UTF-8?q?=ED=95=98=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jdbc/core/JdbcTemplate.java | 6 ++ .../jdbc/core/JdbcTemplateTest.java | 57 +++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/jdbc/src/main/java/org/springframework/jdbc/core/JdbcTemplate.java b/jdbc/src/main/java/org/springframework/jdbc/core/JdbcTemplate.java index 964e65a928..45c117680d 100644 --- a/jdbc/src/main/java/org/springframework/jdbc/core/JdbcTemplate.java +++ b/jdbc/src/main/java/org/springframework/jdbc/core/JdbcTemplate.java @@ -10,6 +10,7 @@ import org.springframework.jdbc.core.exception.DataNotFoundException; import org.springframework.jdbc.core.exception.JdbcTemplateException; import org.springframework.jdbc.datasource.DataSourceUtils; +import org.springframework.transaction.support.TransactionSynchronizationManager; public class JdbcTemplate { @@ -70,6 +71,11 @@ private T executeSql( return preparedStatementExecutor.execute(pst); } catch (final SQLException e) { throw new JdbcTemplateException(e); + } finally { + if (!TransactionSynchronizationManager.isTransactionActive(dataSource)) { + DataSourceUtils.releaseConnection(connection, dataSource); + TransactionSynchronizationManager.unbindResource(dataSource); + } } } } diff --git a/jdbc/src/test/java/org/springframework/jdbc/core/JdbcTemplateTest.java b/jdbc/src/test/java/org/springframework/jdbc/core/JdbcTemplateTest.java index 2508377110..e48700eddc 100644 --- a/jdbc/src/test/java/org/springframework/jdbc/core/JdbcTemplateTest.java +++ b/jdbc/src/test/java/org/springframework/jdbc/core/JdbcTemplateTest.java @@ -3,16 +3,27 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertAll; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import java.sql.Connection; +import java.sql.SQLException; +import javax.sql.DataSource; import org.assertj.core.api.ThrowableAssert.ThrowingCallable; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.springframework.jdbc.core.exception.DataNotFoundException; import org.springframework.jdbc.core.test_supporter.DataSourceConfig; import org.springframework.jdbc.core.test_supporter.DatabasePopulatorUtils; import org.springframework.jdbc.core.test_supporter.User; import org.springframework.jdbc.core.test_supporter.UserDao; +import org.springframework.jdbc.datasource.DataSourceUtils; +import org.springframework.transaction.support.TransactionSynchronizationManager; class JdbcTemplateTest { @@ -92,4 +103,50 @@ void noDataFoundException() { assertThatThrownBy(testTarget) .isInstanceOf(DataNotFoundException.class); } + + @Nested + @DisplayName("트랜잭션이 활성화 여부에 따라 Connection을 close한다.") + class CloseNonTransactionConnection { + + private JdbcTemplate jdbcTemplate; + private DataSource dataSource; + private Connection connection; + + @BeforeEach + void setUp() throws SQLException { + dataSource = spy(DataSourceConfig.getInstance()); + connection = spy(dataSource.getConnection()); + when(dataSource.getConnection()).thenReturn(connection); + jdbcTemplate = new JdbcTemplate(dataSource); + } + + @Test + @DisplayName("트랜잭션이 활성화되어 있지 않으면 close한다.") + void closeNonTransactionConnection() throws SQLException { + final String sql = "insert into users (account, password, email) values (?, ?, ?)"; + + jdbcTemplate.executeUpdate( + sql, + USER_FIXTURE.getAccount(), USER_FIXTURE.getPassword(), USER_FIXTURE.getEmail() + ); + verify(connection, times(1)).close(); + } + + @Test + @DisplayName("트랜잭션이 활성화되어 있으면 close하지 않는다.") + void closeTransactionConnection() throws SQLException { + final String sql = "insert into users (account, password, email) values (?, ?, ?)"; + final Connection connection = DataSourceUtils.getConnection(dataSource); + connection.setAutoCommit(false); + + jdbcTemplate.executeUpdate( + sql, + USER_FIXTURE.getAccount(), USER_FIXTURE.getPassword(), USER_FIXTURE.getEmail() + ); + + verify(connection, never()).close(); + TransactionSynchronizationManager.clear(); + connection.close(); + } + } }