From d15fc85630379dc67e113c65d7ca5d99185ef9a7 Mon Sep 17 00:00:00 2001 From: java-saeng Date: Sat, 7 Oct 2023 14:35:17 +0900 Subject: [PATCH 1/6] =?UTF-8?q?feat=20:=20=ED=8A=B8=EB=9E=9C=EC=9E=AD?= =?UTF-8?q?=EC=85=98=20=EC=84=9C=EB=B9=84=EC=8A=A4=20=EC=B6=94=EC=83=81?= =?UTF-8?q?=ED=99=94=ED=95=98=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../techcourse/service/AppUserService.java | 32 +++++++++++++++ .../com/techcourse/service/TxUserService.java | 38 ++++++++++++++++++ .../com/techcourse/service/UserService.java | 40 ++----------------- ...rviceTest.java => AppUserServiceTest.java} | 7 ++-- 4 files changed, 78 insertions(+), 39 deletions(-) create mode 100644 app/src/main/java/com/techcourse/service/AppUserService.java create mode 100644 app/src/main/java/com/techcourse/service/TxUserService.java rename app/src/test/java/com/techcourse/service/{UserServiceTest.java => AppUserServiceTest.java} (88%) diff --git a/app/src/main/java/com/techcourse/service/AppUserService.java b/app/src/main/java/com/techcourse/service/AppUserService.java new file mode 100644 index 0000000000..94450d766c --- /dev/null +++ b/app/src/main/java/com/techcourse/service/AppUserService.java @@ -0,0 +1,32 @@ +package com.techcourse.service; + +import com.techcourse.dao.UserDao; +import com.techcourse.dao.UserHistoryDao; +import com.techcourse.domain.User; +import com.techcourse.domain.UserHistory; + +public class AppUserService implements UserService { + + private final UserDao userDao; + private final UserHistoryDao userHistoryDao; + + public AppUserService(final UserDao userDao, final UserHistoryDao userHistoryDao) { + this.userDao = userDao; + this.userHistoryDao = userHistoryDao; + } + + public User findById(final long id) { + return userDao.findById(id); + } + + public void insert(final User user) { + userDao.insert(user); + } + + public void changePassword(final long id, final String newPassword, final String createBy) { + final var user = findById(id); + user.changePassword(newPassword); + userDao.update(user); + userHistoryDao.log(new UserHistory(user, createBy)); + } +} diff --git a/app/src/main/java/com/techcourse/service/TxUserService.java b/app/src/main/java/com/techcourse/service/TxUserService.java new file mode 100644 index 0000000000..4d9597f269 --- /dev/null +++ b/app/src/main/java/com/techcourse/service/TxUserService.java @@ -0,0 +1,38 @@ +package com.techcourse.service; + +import com.techcourse.domain.User; +import org.springframework.jdbc.core.TransactionManager; + +public class TxUserService implements UserService { + + private final UserService userService; + + public TxUserService(final UserService userService) { + this.userService = userService; + } + + @Override + public User findById(final long id) { + return userService.findById(id); + } + + @Override + public void insert(final User user) { + userService.insert(user); + } + + @Override + public void changePassword(final long id, final String newPassword, final String createBy) { + TransactionManager.start(); + + try { + userService.changePassword(id, newPassword, createBy); + TransactionManager.commit(); + } catch (Exception e) { + TransactionManager.rollback(); + throw e; + } finally { + TransactionManager.release(); + } + } +} diff --git a/app/src/main/java/com/techcourse/service/UserService.java b/app/src/main/java/com/techcourse/service/UserService.java index 51a88bfbc8..669f722504 100644 --- a/app/src/main/java/com/techcourse/service/UserService.java +++ b/app/src/main/java/com/techcourse/service/UserService.java @@ -1,43 +1,11 @@ package com.techcourse.service; -import com.techcourse.dao.UserDao; -import com.techcourse.dao.UserHistoryDao; import com.techcourse.domain.User; -import com.techcourse.domain.UserHistory; -import org.springframework.jdbc.core.TransactionManager; -public class UserService { +public interface UserService { - private final UserDao userDao; - private final UserHistoryDao userHistoryDao; + User findById(final long id); + void insert(final User user); + void changePassword(final long id, final String newPassword, final String createBy); - public UserService(final UserDao userDao, final UserHistoryDao userHistoryDao) { - this.userDao = userDao; - this.userHistoryDao = userHistoryDao; - } - - public User findById(final long id) { - return userDao.findById(id); - } - - public void insert(final User user) { - userDao.insert(user); - } - - public void changePassword(final long id, final String newPassword, final String createBy) { - final var user = findById(id); - - TransactionManager.start(); - try { - user.changePassword(newPassword); - userDao.update(user); - userHistoryDao.log(new UserHistory(user, createBy)); - TransactionManager.commit(); - } catch (Exception e) { - TransactionManager.rollback(); - throw e; - } finally { - TransactionManager.release(); - } - } } diff --git a/app/src/test/java/com/techcourse/service/UserServiceTest.java b/app/src/test/java/com/techcourse/service/AppUserServiceTest.java similarity index 88% rename from app/src/test/java/com/techcourse/service/UserServiceTest.java rename to app/src/test/java/com/techcourse/service/AppUserServiceTest.java index 83bc1d3505..edc825cc9c 100644 --- a/app/src/test/java/com/techcourse/service/UserServiceTest.java +++ b/app/src/test/java/com/techcourse/service/AppUserServiceTest.java @@ -13,7 +13,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; -class UserServiceTest { +class AppUserServiceTest { private JdbcTemplate jdbcTemplate; private UserDao userDao; @@ -31,7 +31,7 @@ void setUp() { @Test void testChangePassword() { final var userHistoryDao = new UserHistoryDao(jdbcTemplate); - final var userService = new UserService(userDao, userHistoryDao); + final var userService = new AppUserService(userDao, userHistoryDao); final var newPassword = "qqqqq"; final var createBy = "gugu"; @@ -46,7 +46,8 @@ void testChangePassword() { void testTransactionRollback() { // 트랜잭션 롤백 테스트를 위해 mock으로 교체 final var userHistoryDao = new MockUserHistoryDao(jdbcTemplate); - final var userService = new UserService(userDao, userHistoryDao); + final var appUserService = new AppUserService(userDao, userHistoryDao); + final TxUserService userService = new TxUserService(appUserService); final var newPassword = "newPassword"; final var createBy = "gugu"; From 2078f76e5b942504bc95ee68556e23c639227d19 Mon Sep 17 00:00:00 2001 From: java-saeng Date: Sat, 7 Oct 2023 15:00:27 +0900 Subject: [PATCH 2/6] =?UTF-8?q?refactor=20:=20=ED=8A=B8=EB=9E=9C=EC=9E=AD?= =?UTF-8?q?=EC=85=98=20=EB=A7=A4=EB=8B=88=EC=A0=80=EA=B0=80=20=EC=97=AC?= =?UTF-8?q?=EB=9F=AC=20=EA=B0=9C=EC=9D=98=20DataSource=EB=A5=BC=20?= =?UTF-8?q?=EA=B0=80=EC=A7=88=20=EC=88=98=20=EC=9E=88=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/techcourse/service/TxUserService.java | 11 ++++-- .../service/AppUserServiceTest.java | 9 +++-- .../jdbc/core/TransactionManager.java | 37 ++++++++++++------- 3 files changed, 37 insertions(+), 20 deletions(-) diff --git a/app/src/main/java/com/techcourse/service/TxUserService.java b/app/src/main/java/com/techcourse/service/TxUserService.java index 4d9597f269..ef2018cd66 100644 --- a/app/src/main/java/com/techcourse/service/TxUserService.java +++ b/app/src/main/java/com/techcourse/service/TxUserService.java @@ -1,14 +1,17 @@ package com.techcourse.service; import com.techcourse.domain.User; +import javax.sql.DataSource; import org.springframework.jdbc.core.TransactionManager; public class TxUserService implements UserService { private final UserService userService; + private final DataSource dataSource; - public TxUserService(final UserService userService) { + public TxUserService(final UserService userService, final DataSource dataSource) { this.userService = userService; + this.dataSource = dataSource; } @Override @@ -27,12 +30,12 @@ public void changePassword(final long id, final String newPassword, final String try { userService.changePassword(id, newPassword, createBy); - TransactionManager.commit(); + TransactionManager.commit(dataSource); } catch (Exception e) { - TransactionManager.rollback(); + TransactionManager.rollback(dataSource); throw e; } finally { - TransactionManager.release(); + TransactionManager.release(dataSource); } } } diff --git a/app/src/test/java/com/techcourse/service/AppUserServiceTest.java b/app/src/test/java/com/techcourse/service/AppUserServiceTest.java index edc825cc9c..86ccd96540 100644 --- a/app/src/test/java/com/techcourse/service/AppUserServiceTest.java +++ b/app/src/test/java/com/techcourse/service/AppUserServiceTest.java @@ -5,6 +5,7 @@ import com.techcourse.dao.UserHistoryDao; import com.techcourse.domain.User; import com.techcourse.support.jdbc.init.DatabasePopulatorUtils; +import javax.sql.DataSource; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.JdbcTemplate; import org.junit.jupiter.api.BeforeEach; @@ -17,13 +18,15 @@ class AppUserServiceTest { private JdbcTemplate jdbcTemplate; private UserDao userDao; + private DataSource dataSource; @BeforeEach void setUp() { - this.jdbcTemplate = new JdbcTemplate(DataSourceConfig.getInstance()); + dataSource = DataSourceConfig.getInstance(); + this.jdbcTemplate = new JdbcTemplate(dataSource); this.userDao = new UserDao(jdbcTemplate); - DatabasePopulatorUtils.execute(DataSourceConfig.getInstance()); + DatabasePopulatorUtils.execute(dataSource); final var user = new User("gugu", "password", "hkkang@woowahan.com"); userDao.insert(user); } @@ -47,7 +50,7 @@ void testTransactionRollback() { // 트랜잭션 롤백 테스트를 위해 mock으로 교체 final var userHistoryDao = new MockUserHistoryDao(jdbcTemplate); final var appUserService = new AppUserService(userDao, userHistoryDao); - final TxUserService userService = new TxUserService(appUserService); + final TxUserService userService = new TxUserService(appUserService, dataSource); final var newPassword = "newPassword"; final var createBy = "gugu"; diff --git a/jdbc/src/main/java/org/springframework/jdbc/core/TransactionManager.java b/jdbc/src/main/java/org/springframework/jdbc/core/TransactionManager.java index 20ae9aef2a..ec4de13dc6 100644 --- a/jdbc/src/main/java/org/springframework/jdbc/core/TransactionManager.java +++ b/jdbc/src/main/java/org/springframework/jdbc/core/TransactionManager.java @@ -2,11 +2,14 @@ import java.sql.Connection; import java.sql.SQLException; +import java.util.HashMap; +import java.util.Map; import javax.sql.DataSource; +import org.springframework.jdbc.datasource.DataSourceUtils; public class TransactionManager { - private static final ThreadLocal resources = new ThreadLocal<>(); + private static final ThreadLocal> resources = new ThreadLocal<>(); private static final ThreadLocal actualTransactionActive = new ThreadLocal<>(); private TransactionManager() { @@ -18,10 +21,15 @@ public static void start() { public static Connection getConnection(final DataSource dataSource) { if (resources.get() == null) { - createConnectionFrom(dataSource); + resources.set(new HashMap<>()); } - final Connection connection = resources.get(); + final Map resource = resources.get(); + + final Connection connection = resource.getOrDefault( + dataSource, + createConnectionFrom(dataSource) + ); if (isTransactionActive()) { setAutoCommit(connection); @@ -30,17 +38,19 @@ public static Connection getConnection(final DataSource dataSource) { return connection; } - private static void setAutoCommit(final Connection connection) { + private static Connection createConnectionFrom(final DataSource dataSource) { try { - connection.setAutoCommit(false); + return resources.get() + .put(dataSource, dataSource.getConnection()); } catch (SQLException e) { throw new RuntimeException(e); } } - private static void createConnectionFrom(final DataSource dataSource) { + + private static void setAutoCommit(final Connection connection) { try { - resources.set(dataSource.getConnection()); + connection.setAutoCommit(false); } catch (SQLException e) { throw new RuntimeException(e); } @@ -51,8 +61,8 @@ private static boolean isTransactionActive() { return isActive != null && isActive; } - public static void commit() { - final Connection connection = resources.get(); + public static void commit(final DataSource dataSource) { + final Connection connection = resources.get().get(dataSource); try { connection.commit(); @@ -61,10 +71,11 @@ public static void commit() { } } - public static void rollback() { + public static void rollback(final DataSource dataSource) { + final Connection connection = resources.get().get(dataSource); + try { if (isTransactionActive()) { - final Connection connection = resources.get(); connection.rollback(); } } catch (SQLException e) { @@ -72,8 +83,8 @@ public static void rollback() { } } - public static void release() { - final Connection connection = resources.get(); + public static void release(final DataSource dataSource) { + final Connection connection = resources.get().get(dataSource); try { connection.close(); From 44195f0c7d6e44dc3fab412c3ad64ccc8f0a69f0 Mon Sep 17 00:00:00 2001 From: java-saeng Date: Sat, 7 Oct 2023 15:27:38 +0900 Subject: [PATCH 3/6] =?UTF-8?q?refactor=20:=20TransactionManager=20->=20Tr?= =?UTF-8?q?ansactionSynchronizationManager=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/techcourse/service/TxUserService.java | 10 +- .../jdbc/core/JdbcTemplate.java | 3 +- .../jdbc/core/TransactionManager.java | 98 ------------------- .../TransactionSynchronizationManager.java | 92 +++++++++++++++-- 4 files changed, 90 insertions(+), 113 deletions(-) delete mode 100644 jdbc/src/main/java/org/springframework/jdbc/core/TransactionManager.java diff --git a/app/src/main/java/com/techcourse/service/TxUserService.java b/app/src/main/java/com/techcourse/service/TxUserService.java index ef2018cd66..5fcfe3f98d 100644 --- a/app/src/main/java/com/techcourse/service/TxUserService.java +++ b/app/src/main/java/com/techcourse/service/TxUserService.java @@ -2,7 +2,7 @@ import com.techcourse.domain.User; import javax.sql.DataSource; -import org.springframework.jdbc.core.TransactionManager; +import org.springframework.transaction.support.TransactionSynchronizationManager; public class TxUserService implements UserService { @@ -26,16 +26,16 @@ public void insert(final User user) { @Override public void changePassword(final long id, final String newPassword, final String createBy) { - TransactionManager.start(); + TransactionSynchronizationManager.start(); try { userService.changePassword(id, newPassword, createBy); - TransactionManager.commit(dataSource); + TransactionSynchronizationManager.commit(dataSource); } catch (Exception e) { - TransactionManager.rollback(dataSource); + TransactionSynchronizationManager.rollback(dataSource); throw e; } finally { - TransactionManager.release(dataSource); + TransactionSynchronizationManager.release(dataSource); } } } 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 33d271e05d..c0cc63c7fa 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 javax.sql.DataSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.transaction.support.TransactionSynchronizationManager; public class JdbcTemplate { @@ -88,7 +89,7 @@ private List extractResultFrom(final ResultSet resultSet, final RowMapper public void execute(final String sql, final Object... values) { - final Connection connection = TransactionManager.getConnection(dataSource); + final Connection connection = TransactionSynchronizationManager.getConnection(dataSource); try ( final PreparedStatement pstmt = connection.prepareStatement(sql) diff --git a/jdbc/src/main/java/org/springframework/jdbc/core/TransactionManager.java b/jdbc/src/main/java/org/springframework/jdbc/core/TransactionManager.java deleted file mode 100644 index ec4de13dc6..0000000000 --- a/jdbc/src/main/java/org/springframework/jdbc/core/TransactionManager.java +++ /dev/null @@ -1,98 +0,0 @@ -package org.springframework.jdbc.core; - -import java.sql.Connection; -import java.sql.SQLException; -import java.util.HashMap; -import java.util.Map; -import javax.sql.DataSource; -import org.springframework.jdbc.datasource.DataSourceUtils; - -public class TransactionManager { - - private static final ThreadLocal> resources = new ThreadLocal<>(); - private static final ThreadLocal actualTransactionActive = new ThreadLocal<>(); - - private TransactionManager() { - } - - public static void start() { - actualTransactionActive.set(Boolean.TRUE); - } - - public static Connection getConnection(final DataSource dataSource) { - if (resources.get() == null) { - resources.set(new HashMap<>()); - } - - final Map resource = resources.get(); - - final Connection connection = resource.getOrDefault( - dataSource, - createConnectionFrom(dataSource) - ); - - if (isTransactionActive()) { - setAutoCommit(connection); - } - - return connection; - } - - private static Connection createConnectionFrom(final DataSource dataSource) { - try { - return resources.get() - .put(dataSource, dataSource.getConnection()); - } catch (SQLException e) { - throw new RuntimeException(e); - } - } - - - private static void setAutoCommit(final Connection connection) { - try { - connection.setAutoCommit(false); - } catch (SQLException e) { - throw new RuntimeException(e); - } - } - - private static boolean isTransactionActive() { - final Boolean isActive = actualTransactionActive.get(); - return isActive != null && isActive; - } - - public static void commit(final DataSource dataSource) { - final Connection connection = resources.get().get(dataSource); - - try { - connection.commit(); - } catch (SQLException e) { - throw new RuntimeException(e); - } - } - - public static void rollback(final DataSource dataSource) { - final Connection connection = resources.get().get(dataSource); - - try { - if (isTransactionActive()) { - connection.rollback(); - } - } catch (SQLException e) { - throw new RuntimeException(e); - } - } - - public static void release(final DataSource dataSource) { - final Connection connection = resources.get().get(dataSource); - - try { - connection.close(); - } catch (SQLException e) { - throw new RuntimeException(e); - } finally { - actualTransactionActive.remove(); - resources.remove(); - } - } -} diff --git a/jdbc/src/main/java/org/springframework/transaction/support/TransactionSynchronizationManager.java b/jdbc/src/main/java/org/springframework/transaction/support/TransactionSynchronizationManager.java index 715557fc66..88a03c3bbc 100644 --- a/jdbc/src/main/java/org/springframework/transaction/support/TransactionSynchronizationManager.java +++ b/jdbc/src/main/java/org/springframework/transaction/support/TransactionSynchronizationManager.java @@ -1,23 +1,97 @@ package org.springframework.transaction.support; -import javax.sql.DataSource; import java.sql.Connection; +import java.sql.SQLException; +import java.util.HashMap; import java.util.Map; +import javax.sql.DataSource; + +public class TransactionSynchronizationManager { + + private static final ThreadLocal> resources = new ThreadLocal<>(); + private static final ThreadLocal actualTransactionActive = new ThreadLocal<>(); + + private TransactionSynchronizationManager() { + } -public abstract class TransactionSynchronizationManager { + public static void start() { + actualTransactionActive.set(Boolean.TRUE); + } - private static final ThreadLocal> resources = new ThreadLocal<>(); + public static Connection getConnection(final DataSource dataSource) { + if (resources.get() == null) { + resources.set(new HashMap<>()); + } + + final Map resource = resources.get(); - private TransactionSynchronizationManager() {} + final Connection connection = resource.getOrDefault( + dataSource, + createConnectionFrom(dataSource) + ); - public static Connection getResource(DataSource key) { - return null; + if (isTransactionActive()) { + setAutoCommit(connection); } - public static void bindResource(DataSource key, Connection value) { + return connection; + } + + private static Connection createConnectionFrom(final DataSource dataSource) { + try { + return resources.get() + .put(dataSource, dataSource.getConnection()); + } catch (SQLException e) { + throw new RuntimeException(e); } + } + + + private static void setAutoCommit(final Connection connection) { + try { + connection.setAutoCommit(false); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + + private static boolean isTransactionActive() { + final Boolean isActive = actualTransactionActive.get(); + return isActive != null && isActive; + } + + public static void commit(final DataSource dataSource) { + final Connection connection = resources.get().get(dataSource); + + try { + connection.commit(); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + + public static void rollback(final DataSource dataSource) { + final Connection connection = resources.get().get(dataSource); + + try { + if (isTransactionActive()) { + connection.rollback(); + } + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + + public static void release(final DataSource dataSource) { + final Connection connection = resources.get().get(dataSource); - public static Connection unbindResource(DataSource key) { - return null; + try { + connection.close(); + } catch (SQLException e) { + throw new RuntimeException(e); + } finally { + actualTransactionActive.remove(); + resources.remove(); } + } } From 0ccc687c2ec8fdb83786866ebaa7223334675fff Mon Sep 17 00:00:00 2001 From: java-saeng Date: Sat, 7 Oct 2023 15:55:18 +0900 Subject: [PATCH 4/6] =?UTF-8?q?refactor=20:=20TransactionSynchronizationMa?= =?UTF-8?q?nager=EC=97=90=EC=84=9C=20Connection=EC=9D=80=20DataSourceUtils?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=EC=96=BB=EA=B3=A0,=20=EB=8B=AB=EB=8A=94?= =?UTF-8?q?=20=EA=B2=83=EC=9C=BC=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jdbc/core/JdbcTemplate.java | 4 +- .../jdbc/datasource/DataSourceUtils.java | 40 ++++++++-------- .../TransactionSynchronizationManager.java | 47 ++++++++++--------- 3 files changed, 47 insertions(+), 44 deletions(-) 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 c0cc63c7fa..4ae167b7bd 100644 --- a/jdbc/src/main/java/org/springframework/jdbc/core/JdbcTemplate.java +++ b/jdbc/src/main/java/org/springframework/jdbc/core/JdbcTemplate.java @@ -10,7 +10,7 @@ import javax.sql.DataSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.transaction.support.TransactionSynchronizationManager; +import org.springframework.jdbc.datasource.DataSourceUtils; public class JdbcTemplate { @@ -89,7 +89,7 @@ private List extractResultFrom(final ResultSet resultSet, final RowMapper public void execute(final String sql, final Object... values) { - final Connection connection = TransactionSynchronizationManager.getConnection(dataSource); + final Connection connection = DataSourceUtils.getConnection(dataSource); try ( final PreparedStatement pstmt = connection.prepareStatement(sql) diff --git a/jdbc/src/main/java/org/springframework/jdbc/datasource/DataSourceUtils.java b/jdbc/src/main/java/org/springframework/jdbc/datasource/DataSourceUtils.java index 3c40bfec52..8f164810e6 100644 --- a/jdbc/src/main/java/org/springframework/jdbc/datasource/DataSourceUtils.java +++ b/jdbc/src/main/java/org/springframework/jdbc/datasource/DataSourceUtils.java @@ -1,5 +1,6 @@ package org.springframework.jdbc.datasource; +import java.util.function.Function; import org.springframework.jdbc.CannotGetJdbcConnectionException; import org.springframework.transaction.support.TransactionSynchronizationManager; @@ -10,28 +11,29 @@ // 4단계 미션에서 사용할 것 public abstract class DataSourceUtils { - private DataSourceUtils() {} + private DataSourceUtils() { + } - public static Connection getConnection(DataSource dataSource) throws CannotGetJdbcConnectionException { - Connection connection = TransactionSynchronizationManager.getResource(dataSource); - if (connection != null) { - return connection; - } + public static Connection getConnection(DataSource dataSource) { + return TransactionSynchronizationManager.getResource(dataSource) + .orElseGet(() -> createConnection(dataSource)); + } - try { - connection = dataSource.getConnection(); - TransactionSynchronizationManager.bindResource(dataSource, connection); - return connection; - } catch (SQLException ex) { - throw new CannotGetJdbcConnectionException("Failed to obtain JDBC Connection", ex); - } + private static Connection createConnection(final DataSource dataSource) { + try { + final Connection connection = dataSource.getConnection(); + TransactionSynchronizationManager.bindResource(dataSource, connection); + return connection; + } catch (SQLException ex) { + throw new CannotGetJdbcConnectionException("Failed to obtain JDBC Connection", ex); } + } - public static void releaseConnection(Connection connection, DataSource dataSource) { - try { - connection.close(); - } catch (SQLException ex) { - throw new CannotGetJdbcConnectionException("Failed to close JDBC Connection"); - } + public static void releaseConnection(Connection connection) { + try { + connection.close(); + } catch (SQLException ex) { + throw new CannotGetJdbcConnectionException("Failed to close JDBC Connection"); } + } } diff --git a/jdbc/src/main/java/org/springframework/transaction/support/TransactionSynchronizationManager.java b/jdbc/src/main/java/org/springframework/transaction/support/TransactionSynchronizationManager.java index 88a03c3bbc..7d5d6c3119 100644 --- a/jdbc/src/main/java/org/springframework/transaction/support/TransactionSynchronizationManager.java +++ b/jdbc/src/main/java/org/springframework/transaction/support/TransactionSynchronizationManager.java @@ -4,7 +4,9 @@ import java.sql.SQLException; import java.util.HashMap; import java.util.Map; +import java.util.Optional; import javax.sql.DataSource; +import org.springframework.jdbc.datasource.DataSourceUtils; public class TransactionSynchronizationManager { @@ -18,17 +20,14 @@ public static void start() { actualTransactionActive.set(Boolean.TRUE); } - public static Connection getConnection(final DataSource dataSource) { - if (resources.get() == null) { - resources.set(new HashMap<>()); - } - + private static Connection getConnection(final DataSource dataSource) { final Map resource = resources.get(); - final Connection connection = resource.getOrDefault( - dataSource, - createConnectionFrom(dataSource) - ); + final Connection connection = resource.get(dataSource); + + if (connection == null) { + return null; + } if (isTransactionActive()) { setAutoCommit(connection); @@ -37,15 +36,22 @@ public static Connection getConnection(final DataSource dataSource) { return connection; } - private static Connection createConnectionFrom(final DataSource dataSource) { - try { - return resources.get() - .put(dataSource, dataSource.getConnection()); - } catch (SQLException e) { - throw new RuntimeException(e); + public static Optional getResource(final DataSource dataSource) { + if (resources.get() == null) { + return Optional.empty(); } + + return Optional.ofNullable(getConnection(dataSource)); } + public static void bindResource(final DataSource dataSource, final Connection connection) { + if (resources.get() == null) { + resources.set(new HashMap<>()); + } + + resources.get() + .put(dataSource, connection); + } private static void setAutoCommit(final Connection connection) { try { @@ -85,13 +91,8 @@ public static void rollback(final DataSource dataSource) { public static void release(final DataSource dataSource) { final Connection connection = resources.get().get(dataSource); - try { - connection.close(); - } catch (SQLException e) { - throw new RuntimeException(e); - } finally { - actualTransactionActive.remove(); - resources.remove(); - } + DataSourceUtils.releaseConnection(connection); + actualTransactionActive.remove(); + resources.get().remove(dataSource); } } From 1e5a7093e24a7c96bebf8a1bdd7e10d39be0e000 Mon Sep 17 00:00:00 2001 From: java-saeng Date: Sat, 7 Oct 2023 16:10:30 +0900 Subject: [PATCH 5/6] =?UTF-8?q?refactor=20:=20CheckedException=EC=9D=84=20?= =?UTF-8?q?CustomException=EC=9C=BC=EB=A1=9C=20=EC=A0=84=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/springframework/jdbc/core/JdbcTemplate.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) 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 4ae167b7bd..8bf1eb96d2 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 javax.sql.DataSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.dao.DataAccessException; import org.springframework.jdbc.datasource.DataSourceUtils; public class JdbcTemplate { @@ -43,7 +44,7 @@ public Optional query(final String sql, RowMapper rowMapper, final Obj return Optional.ofNullable(result.get(0)); } catch (SQLException e) { log.error(e.getMessage(), e); - throw new RuntimeException(e); + throw new DataAccessException(e); } } @@ -72,7 +73,7 @@ public List queryPlural( return extractResultFrom(resultSet, rowMapper); } catch (SQLException e) { log.error(e.getMessage(), e); - throw new RuntimeException(e); + throw new DataAccessException(e); } } @@ -102,7 +103,7 @@ public void execute(final String sql, final Object... values) { pstmt.executeUpdate(); } catch (SQLException e) { log.error(e.getMessage(), e); - throw new RuntimeException(e); + throw new DataAccessException(e); } } } From 2836fac9188c8cbd9aab71f94c338a4513784bfe Mon Sep 17 00:00:00 2001 From: java-saeng Date: Tue, 10 Oct 2023 11:44:03 +0900 Subject: [PATCH 6/6] =?UTF-8?q?refactor=20:=20release=20=EC=8B=9C=20connec?= =?UTF-8?q?tion=20=EC=98=88=EC=99=B8=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TransactionSynchronizationManager.java | 35 ++++++++++++------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/jdbc/src/main/java/org/springframework/transaction/support/TransactionSynchronizationManager.java b/jdbc/src/main/java/org/springframework/transaction/support/TransactionSynchronizationManager.java index 7d5d6c3119..cd62362f67 100644 --- a/jdbc/src/main/java/org/springframework/transaction/support/TransactionSynchronizationManager.java +++ b/jdbc/src/main/java/org/springframework/transaction/support/TransactionSynchronizationManager.java @@ -6,6 +6,7 @@ import java.util.Map; import java.util.Optional; import javax.sql.DataSource; +import org.springframework.dao.DataAccessException; import org.springframework.jdbc.datasource.DataSourceUtils; public class TransactionSynchronizationManager { @@ -21,7 +22,7 @@ public static void start() { } private static Connection getConnection(final DataSource dataSource) { - final Map resource = resources.get(); + final Map resource = getResources(); final Connection connection = resource.get(dataSource); @@ -30,14 +31,14 @@ private static Connection getConnection(final DataSource dataSource) { } if (isTransactionActive()) { - setAutoCommit(connection); + begin(connection); } return connection; } public static Optional getResource(final DataSource dataSource) { - if (resources.get() == null) { + if (getResources() == null) { return Optional.empty(); } @@ -45,19 +46,19 @@ public static Optional getResource(final DataSource dataSource) { } public static void bindResource(final DataSource dataSource, final Connection connection) { - if (resources.get() == null) { + if (getResources() == null) { resources.set(new HashMap<>()); } - resources.get() + getResources() .put(dataSource, connection); } - private static void setAutoCommit(final Connection connection) { + private static void begin(final Connection connection) { try { connection.setAutoCommit(false); } catch (SQLException e) { - throw new RuntimeException(e); + throw new DataAccessException(e); } } @@ -67,32 +68,40 @@ private static boolean isTransactionActive() { } public static void commit(final DataSource dataSource) { - final Connection connection = resources.get().get(dataSource); + final Connection connection = getResources().get(dataSource); try { connection.commit(); } catch (SQLException e) { - throw new RuntimeException(e); + throw new DataAccessException(e); } } public static void rollback(final DataSource dataSource) { - final Connection connection = resources.get().get(dataSource); + final Connection connection = getResources().get(dataSource); try { if (isTransactionActive()) { connection.rollback(); } } catch (SQLException e) { - throw new RuntimeException(e); + throw new DataAccessException(e); } } public static void release(final DataSource dataSource) { - final Connection connection = resources.get().get(dataSource); + final Connection connection = getResources().get(dataSource); + + if (connection == null) { + throw new DataAccessException("not exist connection"); + } DataSourceUtils.releaseConnection(connection); actualTransactionActive.remove(); - resources.get().remove(dataSource); + getResources().remove(dataSource); + } + + private static Map getResources() { + return resources.get(); } }