From a808ace0844005004d662d3129a972b8eaaa0a23 Mon Sep 17 00:00:00 2001 From: JunDonghyuk Date: Sun, 1 Oct 2023 16:37:13 +0900 Subject: [PATCH 1/5] =?UTF-8?q?feat:=20CustomException=20=EC=A0=95?= =?UTF-8?q?=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../techcourse/dao/exception/UserFoundException.java | 8 ++++++++ .../jdbc/exception/DatabaseResourceException.java | 10 ++++++++++ 2 files changed, 18 insertions(+) create mode 100644 app/src/main/java/com/techcourse/dao/exception/UserFoundException.java create mode 100644 jdbc/src/main/java/org/springframework/jdbc/exception/DatabaseResourceException.java diff --git a/app/src/main/java/com/techcourse/dao/exception/UserFoundException.java b/app/src/main/java/com/techcourse/dao/exception/UserFoundException.java new file mode 100644 index 0000000000..5ffde7eec7 --- /dev/null +++ b/app/src/main/java/com/techcourse/dao/exception/UserFoundException.java @@ -0,0 +1,8 @@ +package com.techcourse.dao.exception; + +public class UserFoundException extends RuntimeException { + + public UserFoundException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/jdbc/src/main/java/org/springframework/jdbc/exception/DatabaseResourceException.java b/jdbc/src/main/java/org/springframework/jdbc/exception/DatabaseResourceException.java new file mode 100644 index 0000000000..9c95b9c88b --- /dev/null +++ b/jdbc/src/main/java/org/springframework/jdbc/exception/DatabaseResourceException.java @@ -0,0 +1,10 @@ +package org.springframework.jdbc.exception; + +import java.sql.SQLException; + +public class DatabaseResourceException extends RuntimeException { + + public DatabaseResourceException(String message, SQLException e) { + super(message, e); + } +} From 72c261cf1be4195fc8ed13d67ef1ddc24bb60dbc Mon Sep 17 00:00:00 2001 From: JunDonghyuk Date: Sun, 1 Oct 2023 16:37:38 +0900 Subject: [PATCH 2/5] =?UTF-8?q?refactor:=20queryForObject=20=EC=98=88?= =?UTF-8?q?=EC=99=B8=20=EC=B2=98=EB=A6=AC=20=EB=B0=8F=20CustomException=20?= =?UTF-8?q?=ED=99=9C=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jdbc/core/JdbcTemplate.java | 56 +++++++------------ 1 file changed, 20 insertions(+), 36 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 b23214b59b..4f459c3658 100644 --- a/jdbc/src/main/java/org/springframework/jdbc/core/JdbcTemplate.java +++ b/jdbc/src/main/java/org/springframework/jdbc/core/JdbcTemplate.java @@ -2,6 +2,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.dao.DataAccessException; +import org.springframework.jdbc.exception.DatabaseResourceException; import javax.sql.DataSource; import java.sql.Connection; @@ -10,7 +12,6 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.List; -import java.util.Optional; public class JdbcTemplate { @@ -31,7 +32,7 @@ public void update(String sql, Object... args) { preparedStatement = getPreparedStatement(connection, sql, args); preparedStatement.executeUpdate(); } catch (SQLException e) { - throw new IllegalArgumentException("Update Exception"); + throw new DatabaseResourceException("Timeout or PreparedStatement is already closed", e); } finally { closeResources(connection, preparedStatement, resultSet); } @@ -46,34 +47,27 @@ public List query(String sql, RowMapper rowMapper, Object... args) { preparedStatement = getPreparedStatement(connection, sql, args); resultSet = getResultSet(preparedStatement); return getObjects(resultSet, rowMapper); - } catch (Exception e) { - throw new IllegalArgumentException("Find Exception"); } finally { closeResources(connection, preparedStatement, resultSet); } } - public Optional queryForObject(String sql, RowMapper rowMapper, Object... args) { - Connection connection = null; - PreparedStatement preparedStatement = null; - ResultSet resultSet = null; - try { - connection = getConnection(); - preparedStatement = getPreparedStatement(connection, sql, args); - resultSet = getResultSet(preparedStatement); - return getObject(resultSet, rowMapper); - } catch (Exception e) { - throw new IllegalArgumentException("Find Exception"); - } finally { - closeResources(connection, preparedStatement, resultSet); + public T queryForObject(String sql, RowMapper rowMapper, Object... args) { + List results = query(sql, rowMapper, args); + if (results.isEmpty()) { + throw new DataAccessException("Data not found."); + } + if (results.size() >= 2) { + throw new DataAccessException("More than one data found"); } + return results.get(0); } private Connection getConnection() { try { return dataSource.getConnection(); } catch (SQLException e) { - throw new IllegalArgumentException("Connection cannot be acquired."); + throw new DatabaseResourceException("Connection cannot be acquired.", e); } } @@ -85,7 +79,7 @@ private PreparedStatement getPreparedStatement(Connection connection, String sql } return preparedStatement; } catch (SQLException e) { - throw new IllegalArgumentException("PreparedStatement cannot be acquired."); + throw new DatabaseResourceException("PreparedStatement cannot be acquired.", e); } } @@ -93,32 +87,22 @@ private ResultSet getResultSet(PreparedStatement preparedStatement) { try { return preparedStatement.executeQuery(); } catch (SQLException e) { - throw new IllegalArgumentException("ResultSet cannot be acquired."); + throw new DatabaseResourceException( + "ResultSet cannot be acquired or PreparedStatement is already closed.", e); } } private List getObjects(ResultSet resultSet, RowMapper rowMapper) { List results = new ArrayList<>(); - while (true) { - Optional result = getObject(resultSet, rowMapper); - if (result.isPresent()) { - results.add(result.get()); - continue; - } - break; - } - return results; - } - - private Optional getObject(ResultSet resultSet, RowMapper rowMapper) { try { - if (resultSet.next()) { - return Optional.of(rowMapper.map(resultSet)); + while (resultSet.next()) { + T result = rowMapper.map(resultSet); + results.add(result); } - return Optional.empty(); } catch (SQLException e) { - throw new IllegalArgumentException("Mapping fail"); + throw new DatabaseResourceException("ResultSet is already closed", e); } + return results; } private void closeResources(Connection connection, From 3fda3c9a7ff9f670b5bb13de682328ef1dfd260c Mon Sep 17 00:00:00 2001 From: JunDonghyuk Date: Sun, 1 Oct 2023 16:37:57 +0900 Subject: [PATCH 3/5] =?UTF-8?q?refactor:=20Jdbctemplate=20=EC=8A=A4?= =?UTF-8?q?=ED=8E=99=EB=B3=80=EA=B2=BD=EC=97=90=20=EC=9D=98=ED=95=9C=20?= =?UTF-8?q?=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 --- .../main/java/com/techcourse/dao/UserDao.java | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/techcourse/dao/UserDao.java b/app/src/main/java/com/techcourse/dao/UserDao.java index 29bf65de00..3fe43cf2ef 100644 --- a/app/src/main/java/com/techcourse/dao/UserDao.java +++ b/app/src/main/java/com/techcourse/dao/UserDao.java @@ -1,8 +1,10 @@ package com.techcourse.dao; +import com.techcourse.dao.exception.UserFoundException; import com.techcourse.domain.User; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; @@ -41,14 +43,20 @@ public List findAll() { public User findById(final Long id) { String sql = "select id, account, password, email from users where id = ?"; - return jdbcTemplate.queryForObject(sql, rowMapper(), id) - .orElseThrow(() -> new IllegalArgumentException("User not found")); + try { + return jdbcTemplate.queryForObject(sql, rowMapper(), id); + } catch (DataAccessException e) { + throw new UserFoundException("유저가 없거나 2명 이상 입니다.", e); + } } public User findByAccount(final String account) { String sql = "select id, account, password, email from users where account = ?"; - return jdbcTemplate.queryForObject(sql, rowMapper(), account) - .orElseThrow(() -> new IllegalArgumentException("User not found")); + try { + return jdbcTemplate.queryForObject(sql, rowMapper(), account); + } catch (DataAccessException e) { + throw new UserFoundException("유저가 없거나 2명 이상 입니다.", e); + } } public RowMapper rowMapper() { From 94859206fb985ef42c01b6ce6729382d16c396c1 Mon Sep 17 00:00:00 2001 From: JunDonghyuk Date: Tue, 3 Oct 2023 16:10:13 +0900 Subject: [PATCH 4/5] =?UTF-8?q?refactor:=20test=20=EB=A1=A4=EB=B0=B1=20?= =?UTF-8?q?=EC=95=88=EB=90=98=EB=8A=94=20=EC=83=81=ED=99=A9=20=EB=95=8C?= =?UTF-8?q?=EB=AC=B8=EC=97=90=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/test/java/com/techcourse/dao/UserDaoTest.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/src/test/java/com/techcourse/dao/UserDaoTest.java b/app/src/test/java/com/techcourse/dao/UserDaoTest.java index 773d7faf82..45d216e665 100644 --- a/app/src/test/java/com/techcourse/dao/UserDaoTest.java +++ b/app/src/test/java/com/techcourse/dao/UserDaoTest.java @@ -3,16 +3,18 @@ import com.techcourse.config.DataSourceConfig; import com.techcourse.domain.User; import com.techcourse.support.jdbc.init.DatabasePopulatorUtils; -import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; import static org.assertj.core.api.Assertions.assertThat; +@TestInstance(TestInstance.Lifecycle.PER_CLASS) class UserDaoTest { private UserDao userDao; - @BeforeEach + @BeforeAll void setup() { DatabasePopulatorUtils.execute(DataSourceConfig.getInstance()); From cab40e496422c0c731ffeac95f07be2da620c8af Mon Sep 17 00:00:00 2001 From: JunDonghyuk Date: Tue, 3 Oct 2023 16:14:30 +0900 Subject: [PATCH 5/5] =?UTF-8?q?refactor:=20update,=20query=20=ED=85=9C?= =?UTF-8?q?=ED=94=8C=EB=A6=BF=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jdbc/core/JdbcTemplate.java | 84 +++++++------------ 1 file changed, 31 insertions(+), 53 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 4f459c3658..e18eac0c1b 100644 --- a/jdbc/src/main/java/org/springframework/jdbc/core/JdbcTemplate.java +++ b/jdbc/src/main/java/org/springframework/jdbc/core/JdbcTemplate.java @@ -12,6 +12,7 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.List; +import java.util.function.Function; public class JdbcTemplate { @@ -24,32 +25,15 @@ public JdbcTemplate(final DataSource dataSource) { } public void update(String sql, Object... args) { - Connection connection = null; - PreparedStatement preparedStatement = null; - ResultSet resultSet = null; - try { - connection = getConnection(); - preparedStatement = getPreparedStatement(connection, sql, args); - preparedStatement.executeUpdate(); - } catch (SQLException e) { - throw new DatabaseResourceException("Timeout or PreparedStatement is already closed", e); - } finally { - closeResources(connection, preparedStatement, resultSet); - } + template(this::executeUpdate, sql, args); } public List query(String sql, RowMapper rowMapper, Object... args) { - Connection connection = null; - PreparedStatement preparedStatement = null; - ResultSet resultSet = null; - try { - connection = getConnection(); - preparedStatement = getPreparedStatement(connection, sql, args); - resultSet = getResultSet(preparedStatement); + Function> query = preparedStatement -> { + ResultSet resultSet = executeQuery(preparedStatement); return getObjects(resultSet, rowMapper); - } finally { - closeResources(connection, preparedStatement, resultSet); - } + }; + return template(query, sql, args); } public T queryForObject(String sql, RowMapper rowMapper, Object... args) { @@ -63,27 +47,16 @@ public T queryForObject(String sql, RowMapper rowMapper, Object... args) return results.get(0); } - private Connection getConnection() { + private int executeUpdate(PreparedStatement preparedStatement) { try { - return dataSource.getConnection(); - } catch (SQLException e) { - throw new DatabaseResourceException("Connection cannot be acquired.", e); - } - } - - private PreparedStatement getPreparedStatement(Connection connection, String sql, Object... args) { - try { - PreparedStatement preparedStatement = connection.prepareStatement(sql); - for (int idx = 1; idx <= args.length; idx++) { - preparedStatement.setObject(idx, args[idx - 1]); - } - return preparedStatement; + return preparedStatement.executeUpdate(); } catch (SQLException e) { - throw new DatabaseResourceException("PreparedStatement cannot be acquired.", e); + throw new DatabaseResourceException( + "Database access error.", e); } } - private ResultSet getResultSet(PreparedStatement preparedStatement) { + private ResultSet executeQuery(PreparedStatement preparedStatement) { try { return preparedStatement.executeQuery(); } catch (SQLException e) { @@ -105,28 +78,33 @@ private List getObjects(ResultSet resultSet, RowMapper rowMapper) { return results; } - private void closeResources(Connection connection, - PreparedStatement preparedStatement, - ResultSet resultSet) { - try { - if (resultSet != null) { - resultSet.close(); - } - } catch (SQLException ignored) { + private T template(Function function, String sql, Object... args) { + try ( + Connection connection = getConnection(); + PreparedStatement preparedStatement = getPreparedStatement(connection, sql, args)) { + return function.apply(preparedStatement); + } catch (SQLException e) { + throw new IllegalArgumentException(); } + } + private Connection getConnection() { try { - if (preparedStatement != null) { - preparedStatement.close(); - } - } catch (SQLException ignored) { + return dataSource.getConnection(); + } catch (SQLException e) { + throw new DatabaseResourceException("Connection cannot be acquired.", e); } + } + private PreparedStatement getPreparedStatement(Connection connection, String sql, Object... args) { try { - if (connection != null) { - connection.close(); + PreparedStatement preparedStatement = connection.prepareStatement(sql); + for (int idx = 1; idx <= args.length; idx++) { + preparedStatement.setObject(idx, args[idx - 1]); } - } catch (SQLException ignored) { + return preparedStatement; + } catch (SQLException e) { + throw new DatabaseResourceException("PreparedStatement cannot be acquired.", e); } } }