From 88ffa927217325b0b40cb2e636e6aa5f51f19976 Mon Sep 17 00:00:00 2001 From: swonny Date: Sat, 14 Oct 2023 20:07:12 +0900 Subject: [PATCH] =?UTF-8?q?refactor:=20=EC=98=88=EC=99=B8=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=20=EB=A1=9C=EC=A7=81=EC=9D=84=20TransactionManager?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=EC=88=98=ED=96=89=ED=95=98=EB=8F=84?= =?UTF-8?q?=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 --- .../main/java/com/techcourse/dao/UserDao.java | 13 +++--- .../com/techcourse/dao/UserHistoryDao.java | 4 +- .../techcourse/service/AppUserService.java | 8 ++-- .../service/TransactionCallback.java | 4 +- .../service/TransactionManager.java | 14 ++++--- .../com/techcourse/service/UserService.java | 8 ++-- .../service/AppUserServiceTest.java | 6 ++- .../jdbc/core/JdbcTemplate.java | 42 +++++++------------ .../jdbc/datasource/DataSourceUtils.java | 3 +- .../TransactionSynchronizationManager.java | 7 ++-- 10 files changed, 57 insertions(+), 52 deletions(-) diff --git a/app/src/main/java/com/techcourse/dao/UserDao.java b/app/src/main/java/com/techcourse/dao/UserDao.java index dbaa46c96c..22f22d0415 100644 --- a/app/src/main/java/com/techcourse/dao/UserDao.java +++ b/app/src/main/java/com/techcourse/dao/UserDao.java @@ -6,6 +6,7 @@ import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; +import java.sql.SQLException; import java.util.List; public class UserDao { @@ -25,14 +26,14 @@ public UserDao(final JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } - public int insert(final User user) { + public int insert(final User user) throws SQLException { final var sql = "insert into users (account, password, email) values (?, ?, ?)"; log.debug("query : {}", sql); return updateQuery(sql, user.getAccount(), user.getPassword(), user.getEmail()); } - private int updateQuery(final String sql, final Object... objects) { + private int updateQuery(final String sql, final Object... objects) throws SQLException { final int updatedRows = jdbcTemplate.update(sql, objects); if (updatedRows < 1) { throw new RuntimeException("저장된 데이터가 없습니다."); @@ -40,14 +41,14 @@ private int updateQuery(final String sql, final Object... objects) { return updatedRows; } - public int update(final User user) { + public int update(final User user) throws SQLException { final var sql = "update users set (account, password, email) = (?, ?, ?)"; log.debug("query : {}", sql); return updateQuery(sql, user.getAccount(), user.getPassword(), user.getEmail()); } - public List findAll() { + public List findAll() throws SQLException { final var sql = "select id, account, password, email from users"; final List users = jdbcTemplate.query(sql, userRowMapper); @@ -56,7 +57,7 @@ public List findAll() { return users; } - public User findById(final Long id) { + public User findById(final Long id) throws SQLException { final var sql = "select id, account, password, email from users where id = ?"; final User user = jdbcTemplate.queryForObject(sql, userRowMapper, id) .orElseThrow(() -> new RuntimeException("찾는 사용자가 존재하지 않습니다.")); @@ -66,7 +67,7 @@ public User findById(final Long id) { return user; } - public User findByAccount(final String account) { + public User findByAccount(final String account) throws SQLException { final var sql = "select id, account, password, email from users where account = ?"; final User user = jdbcTemplate.queryForObject(sql, userRowMapper, account) .orElseThrow(() -> new RuntimeException("찾는 사용자가 존재하지 않습니다.")); diff --git a/app/src/main/java/com/techcourse/dao/UserHistoryDao.java b/app/src/main/java/com/techcourse/dao/UserHistoryDao.java index b67bc6b889..253528653b 100644 --- a/app/src/main/java/com/techcourse/dao/UserHistoryDao.java +++ b/app/src/main/java/com/techcourse/dao/UserHistoryDao.java @@ -5,6 +5,8 @@ import org.slf4j.LoggerFactory; import org.springframework.jdbc.core.JdbcTemplate; +import java.sql.SQLException; + public class UserHistoryDao { private static final Logger log = LoggerFactory.getLogger(UserHistoryDao.class); @@ -15,7 +17,7 @@ public UserHistoryDao(final JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } - public void log(final UserHistory userHistory) { + public void log(final UserHistory userHistory) throws SQLException { final var sql = "insert into user_history (user_id, account, password, email, created_at, created_by) values (?, ?, ?, ?, ?, ?)"; jdbcTemplate.update( sql, diff --git a/app/src/main/java/com/techcourse/service/AppUserService.java b/app/src/main/java/com/techcourse/service/AppUserService.java index 52e720a856..e865f4735c 100644 --- a/app/src/main/java/com/techcourse/service/AppUserService.java +++ b/app/src/main/java/com/techcourse/service/AppUserService.java @@ -5,6 +5,8 @@ import com.techcourse.domain.User; import com.techcourse.domain.UserHistory; +import java.sql.SQLException; + public class AppUserService implements UserService { private final UserDao userDao; @@ -16,17 +18,17 @@ public AppUserService(final UserDao userDao, final UserHistoryDao userHistoryDao } @Override - public User findById(final long id) { + public User findById(final long id) throws SQLException { return userDao.findById(id); } @Override - public void insert(final User user) { + public void insert(final User user) throws SQLException { userDao.insert(user); } @Override - public void changePassword(long id, final String newPassword, final String createBy) { + public void changePassword(long id, final String newPassword, final String createBy) throws SQLException { final var user = findById(id); user.changePassword(newPassword); userDao.update(user); diff --git a/app/src/main/java/com/techcourse/service/TransactionCallback.java b/app/src/main/java/com/techcourse/service/TransactionCallback.java index 25695e211f..c160dac30b 100644 --- a/app/src/main/java/com/techcourse/service/TransactionCallback.java +++ b/app/src/main/java/com/techcourse/service/TransactionCallback.java @@ -1,7 +1,9 @@ package com.techcourse.service; +import java.sql.SQLException; + @FunctionalInterface public interface TransactionCallback { - T execute(); + T execute() throws SQLException; } diff --git a/app/src/main/java/com/techcourse/service/TransactionManager.java b/app/src/main/java/com/techcourse/service/TransactionManager.java index af826a0455..9c28147150 100644 --- a/app/src/main/java/com/techcourse/service/TransactionManager.java +++ b/app/src/main/java/com/techcourse/service/TransactionManager.java @@ -17,14 +17,18 @@ public TransactionManager(final DataSource dataSource) { } public T execute(final TransactionCallback callback) { - final Connection connection = TransactionSynchronizationManager.startNewTransaction(dataSource); + try { + final Connection connection = TransactionSynchronizationManager.startNewTransaction(dataSource); - final T result = callback.execute(); + final T result = callback.execute(); - commitTransaction(connection); - TransactionSynchronizationManager.finishTransaction(dataSource); + commitTransaction(connection); + TransactionSynchronizationManager.finishTransaction(dataSource); - return result; + return result; + } catch (final SQLException ex) { + throw new RuntimeException("실행 중 예외가 발생했습니다."); + } } public static void commitTransaction(final Connection connection) { diff --git a/app/src/main/java/com/techcourse/service/UserService.java b/app/src/main/java/com/techcourse/service/UserService.java index b14dbcacbf..7f2430e9ed 100644 --- a/app/src/main/java/com/techcourse/service/UserService.java +++ b/app/src/main/java/com/techcourse/service/UserService.java @@ -2,11 +2,13 @@ import com.techcourse.domain.User; +import java.sql.SQLException; + public interface UserService { - User findById(final long id); + User findById(final long id) throws SQLException; - void insert(final User user); + void insert(final User user) throws SQLException; - void changePassword(final long id, final String newPassword, final String createBy); + void changePassword(final long id, final String newPassword, final String createBy) throws SQLException; } diff --git a/app/src/test/java/com/techcourse/service/AppUserServiceTest.java b/app/src/test/java/com/techcourse/service/AppUserServiceTest.java index 04e450099f..98cce20653 100644 --- a/app/src/test/java/com/techcourse/service/AppUserServiceTest.java +++ b/app/src/test/java/com/techcourse/service/AppUserServiceTest.java @@ -10,6 +10,7 @@ import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.JdbcTemplate; +import javax.sql.DataSource; import java.sql.SQLException; import static org.assertj.core.api.Assertions.assertThat; @@ -25,13 +26,14 @@ void setUp() throws SQLException { this.jdbcTemplate = new JdbcTemplate(DataSourceConfig.getInstance()); this.userDao = new UserDao(jdbcTemplate); - DatabasePopulatorUtils.execute(DataSourceConfig.getInstance()); + final DataSource dataSource = DataSourceConfig.getInstance(); + DatabasePopulatorUtils.execute(dataSource); final var user = new User("gugu", "password", "hkkang@woowahan.com"); userDao.insert(user); } @Test - void testChangePassword() { + void testChangePassword() throws SQLException { final var userHistoryDao = new UserHistoryDao(jdbcTemplate); final var userService = new AppUserService(userDao, userHistoryDao); 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 ad831ce2b1..714a1402d6 100644 --- a/jdbc/src/main/java/org/springframework/jdbc/core/JdbcTemplate.java +++ b/jdbc/src/main/java/org/springframework/jdbc/core/JdbcTemplate.java @@ -2,7 +2,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.jdbc.CannotGetJdbcConnectionException; +import org.springframework.dao.DataAccessException; import org.springframework.transaction.support.TransactionSynchronizationManager; import javax.sql.DataSource; @@ -25,20 +25,20 @@ public JdbcTemplate(final DataSource dataSource) { this.dataSource = dataSource; } - public Optional queryForObject(final String sql, final RowMapper rowMapper, final Object... parameters) { + public Optional queryForObject(final String sql, final RowMapper rowMapper, final Object... parameters) throws SQLException { return execute(sql, preparedStatement -> { final ResultSet resultSet = preparedStatement.executeQuery(); if (resultSet.next()) { return Optional.of(rowMapper.mapRow(resultSet)); } if (!resultSet.isLast()) { - throw new RuntimeException("단일 데이터가 아닙니다."); + throw new DataAccessException("단일 데이터가 아닙니다."); } return Optional.empty(); }, parameters); } - public List query(final String sql, final RowMapper rowMapper) { + public List query(final String sql, final RowMapper rowMapper) throws SQLException { return execute(sql, preparedStatement -> { final ResultSet resultSet = preparedStatement.executeQuery(); final List objects = new ArrayList<>(); @@ -50,34 +50,24 @@ public List query(final String sql, final RowMapper rowMapper) { }); } - public int update(final String sql, final Object... parameters) { + public int update(final String sql, final Object... parameters) throws SQLException { return execute(sql, PreparedStatement::executeUpdate, parameters); } - public T execute(final String sql, final ExecuteQueryCallback callBack, final Object... objects) { - try { - final PreparedStatement preparedStatement = createPreparedStatement(sql); - setPreparedStatement(preparedStatement, objects); + public T execute( + final String sql, + final ExecuteQueryCallback callBack, + final Object... objects + ) throws SQLException { + final PreparedStatement preparedStatement = createPreparedStatement(sql); + setPreparedStatement(preparedStatement, objects); - final T result = callBack.execute(preparedStatement); - TransactionSynchronizationManager.commitTransaction(dataSource); - - return result; - } catch (final SQLException ex) { - throw new RuntimeException("실행 중 예외가 발생했습니다."); - } + return callBack.execute(preparedStatement); } - private PreparedStatement createPreparedStatement(final String sql) { - try { - final Connection connection = TransactionSynchronizationManager.getResource(dataSource); - return connection.prepareStatement(sql); - } catch (SQLException ex) { - TransactionSynchronizationManager.rollback(dataSource); - - log.error(ex.getMessage()); - throw new CannotGetJdbcConnectionException("jdbc 연결에 실패했습니다."); - } + private PreparedStatement createPreparedStatement(final String sql) throws SQLException { + final Connection connection = TransactionSynchronizationManager.getResource(dataSource); + return connection.prepareStatement(sql); } private void setPreparedStatement(final PreparedStatement preparedStatement, final Object[] parameters) throws SQLException { 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 825156bd9a..8d3d0c9a0e 100644 --- a/jdbc/src/main/java/org/springframework/jdbc/datasource/DataSourceUtils.java +++ b/jdbc/src/main/java/org/springframework/jdbc/datasource/DataSourceUtils.java @@ -1,7 +1,6 @@ package org.springframework.jdbc.datasource; import org.springframework.jdbc.CannotGetJdbcConnectionException; -import org.springframework.transaction.support.TransactionSynchronizationManager; import javax.sql.DataSource; import java.sql.Connection; @@ -14,7 +13,7 @@ private DataSourceUtils() { public static Connection getConnection(final DataSource dataSource) throws CannotGetJdbcConnectionException, SQLException { try { - return TransactionSynchronizationManager.getResource(dataSource); + return dataSource.getConnection(); } catch (SQLException ex) { throw new CannotGetJdbcConnectionException("Failed to obtain JDBC Connection", ex); } 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 8758f95954..6be3352e5f 100644 --- a/jdbc/src/main/java/org/springframework/transaction/support/TransactionSynchronizationManager.java +++ b/jdbc/src/main/java/org/springframework/transaction/support/TransactionSynchronizationManager.java @@ -16,9 +16,10 @@ public abstract class TransactionSynchronizationManager { private TransactionSynchronizationManager() { } - public static Connection getResource(final DataSource dataSource) throws SQLException { - if (!isActive.get() || !resources.get().containsKey(dataSource)) { - throw new RuntimeException("시작한 트랜잭션이 없습니다."); + public static Connection getResource(final DataSource dataSource) { + if (!resources.get().containsKey(dataSource)) { + final Connection connection = startNewTransaction(dataSource); + resources.get().put(dataSource, connection); } return resources.get().get(dataSource); }