From 2ccfb6aaf564329406766839cdc5efc53bb83f67 Mon Sep 17 00:00:00 2001 From: aak2075 Date: Thu, 28 Sep 2023 21:06:02 +0900 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20jdbctemplate=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/techcourse/dao/UserDao.java | 105 ++++-------------- .../java/com/techcourse/dao/UserDaoTest.java | 1 + .../dao/EmptyResultAccessException.java | 4 + .../core/ArgumentPreparedStatementSetter.java | 20 ++++ .../jdbc/core/JdbcTemplate.java | 49 ++++++++ .../jdbc/core/PreparedStatementSetter.java | 10 ++ .../springframework/jdbc/core/RowMapper.java | 10 ++ 7 files changed, 115 insertions(+), 84 deletions(-) create mode 100644 jdbc/src/main/java/org/springframework/dao/EmptyResultAccessException.java create mode 100644 jdbc/src/main/java/org/springframework/jdbc/core/ArgumentPreparedStatementSetter.java create mode 100644 jdbc/src/main/java/org/springframework/jdbc/core/PreparedStatementSetter.java create mode 100644 jdbc/src/main/java/org/springframework/jdbc/core/RowMapper.java diff --git a/app/src/main/java/com/techcourse/dao/UserDao.java b/app/src/main/java/com/techcourse/dao/UserDao.java index d14c545f34..57cb0f618c 100644 --- a/app/src/main/java/com/techcourse/dao/UserDao.java +++ b/app/src/main/java/com/techcourse/dao/UserDao.java @@ -1,121 +1,58 @@ package com.techcourse.dao; import com.techcourse.domain.User; -import org.springframework.jdbc.core.JdbcTemplate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; import javax.sql.DataSource; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; import java.util.List; public class UserDao { private static final Logger log = LoggerFactory.getLogger(UserDao.class); - private final DataSource dataSource; + private final JdbcTemplate jdbcTemplate; + + private RowMapper rowMapper = (rs, rowNum) -> { + Long id = rs.getLong("id"); + String account = rs.getString("account"); + String password = rs.getString("password"); + String email = rs.getString("email"); + return new User(id, account, password, email); + }; public UserDao(final DataSource dataSource) { - this.dataSource = dataSource; + this(new JdbcTemplate(dataSource)); } public UserDao(final JdbcTemplate jdbcTemplate) { - this.dataSource = null; + this.jdbcTemplate = jdbcTemplate; } public void insert(final User user) { final var sql = "insert into users (account, password, email) values (?, ?, ?)"; - - Connection conn = null; - PreparedStatement pstmt = null; - try { - conn = dataSource.getConnection(); - pstmt = conn.prepareStatement(sql); - - log.debug("query : {}", sql); - - pstmt.setString(1, user.getAccount()); - pstmt.setString(2, user.getPassword()); - pstmt.setString(3, user.getEmail()); - pstmt.executeUpdate(); - } catch (SQLException e) { - log.error(e.getMessage(), e); - throw new RuntimeException(e); - } finally { - try { - if (pstmt != null) { - pstmt.close(); - } - } catch (SQLException ignored) {} - - try { - if (conn != null) { - conn.close(); - } - } catch (SQLException ignored) {} - } + jdbcTemplate.update(sql, user.getAccount(), user.getPassword(), user.getEmail()); } public void update(final User user) { - // todo + final var sql = "update users set account = ?, password = ?, email = ? where id = ?"; + jdbcTemplate.update(sql, user.getAccount(), user.getPassword(), user.getEmail(), user.getId()); } public List findAll() { - // todo - return null; + final var sql = "select id, account, password, email from users"; + return jdbcTemplate.query(sql, rowMapper); } public User findById(final Long id) { final var sql = "select id, account, password, email from users where id = ?"; - - Connection conn = null; - PreparedStatement pstmt = null; - ResultSet rs = null; - try { - conn = dataSource.getConnection(); - pstmt = conn.prepareStatement(sql); - pstmt.setLong(1, id); - rs = pstmt.executeQuery(); - - log.debug("query : {}", sql); - - if (rs.next()) { - return new User( - rs.getLong(1), - rs.getString(2), - rs.getString(3), - rs.getString(4)); - } - return null; - } catch (SQLException e) { - log.error(e.getMessage(), e); - throw new RuntimeException(e); - } finally { - try { - if (rs != null) { - rs.close(); - } - } catch (SQLException ignored) {} - - try { - if (pstmt != null) { - pstmt.close(); - } - } catch (SQLException ignored) {} - - try { - if (conn != null) { - conn.close(); - } - } catch (SQLException ignored) {} - } + return jdbcTemplate.queryForObject(sql, rowMapper, id); } public User findByAccount(final String account) { - // todo - return null; + final var sql = "select id, account, password, email from users where account = ?"; + return jdbcTemplate.queryForObject(sql, rowMapper, account); } } diff --git a/app/src/test/java/com/techcourse/dao/UserDaoTest.java b/app/src/test/java/com/techcourse/dao/UserDaoTest.java index 773d7faf82..50e1ba35b9 100644 --- a/app/src/test/java/com/techcourse/dao/UserDaoTest.java +++ b/app/src/test/java/com/techcourse/dao/UserDaoTest.java @@ -5,6 +5,7 @@ import com.techcourse.support.jdbc.init.DatabasePopulatorUtils; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.springframework.jdbc.core.JdbcTemplate; import static org.assertj.core.api.Assertions.assertThat; diff --git a/jdbc/src/main/java/org/springframework/dao/EmptyResultAccessException.java b/jdbc/src/main/java/org/springframework/dao/EmptyResultAccessException.java new file mode 100644 index 0000000000..4868c8bc7f --- /dev/null +++ b/jdbc/src/main/java/org/springframework/dao/EmptyResultAccessException.java @@ -0,0 +1,4 @@ +package org.springframework.dao; + +public class EmptyResultAccessException extends RuntimeException { +} diff --git a/jdbc/src/main/java/org/springframework/jdbc/core/ArgumentPreparedStatementSetter.java b/jdbc/src/main/java/org/springframework/jdbc/core/ArgumentPreparedStatementSetter.java new file mode 100644 index 0000000000..5f037d0aa9 --- /dev/null +++ b/jdbc/src/main/java/org/springframework/jdbc/core/ArgumentPreparedStatementSetter.java @@ -0,0 +1,20 @@ +package org.springframework.jdbc.core; + +import java.sql.PreparedStatement; +import java.sql.SQLException; + +public class ArgumentPreparedStatementSetter implements PreparedStatementSetter{ + + private final Object[] args; + + public ArgumentPreparedStatementSetter(Object[] args) { + this.args = args; + } + + @Override + public void setValues(PreparedStatement pstmt) throws SQLException { + for (int i = 0; i < args.length; i++) { + pstmt.setObject(i + 1, args[i]); + } + } +} 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 52a0d30a17..9051b7942c 100644 --- a/jdbc/src/main/java/org/springframework/jdbc/core/JdbcTemplate.java +++ b/jdbc/src/main/java/org/springframework/jdbc/core/JdbcTemplate.java @@ -2,8 +2,16 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.dao.DataAccessException; +import org.springframework.dao.EmptyResultAccessException; import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; public class JdbcTemplate { @@ -14,4 +22,45 @@ public class JdbcTemplate { public JdbcTemplate(final DataSource dataSource) { this.dataSource = dataSource; } + + public List query(final String sql, final RowMapper rowMapper, final Object... args) { + try (Connection conn = dataSource.getConnection(); + PreparedStatement pstmt = conn.prepareStatement(sql)) { + log.debug("query : {}", sql); + + PreparedStatementSetter pstSetter = new ArgumentPreparedStatementSetter(args); + pstSetter.setValues(pstmt); + ResultSet resultSet = pstmt.executeQuery(); + + List results = new ArrayList<>(); + int rowNum = 0; + while (resultSet.next()) { + results.add(rowMapper.mapRow(resultSet, rowNum++)); + } + return results; + } catch (SQLException e) { + throw new DataAccessException(e); + } + } + + public T queryForObject(final String sql, final RowMapper rowMapper, final Object... args) { + List results = query(sql, rowMapper, args); + if (results.isEmpty()) { + throw new EmptyResultAccessException(); + } + return results.get(0); + } + + public void update(final String sql, final Object... args) { + try (Connection conn = dataSource.getConnection(); + PreparedStatement pstmt = conn.prepareStatement(sql)) { + log.debug("query : {}", sql); + + PreparedStatementSetter pstSetter = new ArgumentPreparedStatementSetter(args); + pstSetter.setValues(pstmt); + pstmt.executeUpdate(); + } catch (SQLException e) { + throw new DataAccessException(e); + } + } } diff --git a/jdbc/src/main/java/org/springframework/jdbc/core/PreparedStatementSetter.java b/jdbc/src/main/java/org/springframework/jdbc/core/PreparedStatementSetter.java new file mode 100644 index 0000000000..5c62787886 --- /dev/null +++ b/jdbc/src/main/java/org/springframework/jdbc/core/PreparedStatementSetter.java @@ -0,0 +1,10 @@ +package org.springframework.jdbc.core; + +import java.sql.PreparedStatement; +import java.sql.SQLException; + +@FunctionalInterface +public interface PreparedStatementSetter { + + void setValues(PreparedStatement preparedStatement) throws SQLException; +} diff --git a/jdbc/src/main/java/org/springframework/jdbc/core/RowMapper.java b/jdbc/src/main/java/org/springframework/jdbc/core/RowMapper.java new file mode 100644 index 0000000000..b1d56e4b25 --- /dev/null +++ b/jdbc/src/main/java/org/springframework/jdbc/core/RowMapper.java @@ -0,0 +1,10 @@ +package org.springframework.jdbc.core; + +import java.sql.ResultSet; +import java.sql.SQLException; + +@FunctionalInterface +public interface RowMapper { + + T mapRow(ResultSet rs, int rowNum) throws SQLException; +} From c71c3852821bfeec4d20d1e6b3ef8b04198585c0 Mon Sep 17 00:00:00 2001 From: aak2075 Date: Thu, 28 Sep 2023 21:10:50 +0900 Subject: [PATCH 2/3] =?UTF-8?q?refactor:=20=EB=A9=94=EC=84=9C=EB=93=9C=20?= =?UTF-8?q?=EC=88=9C=EC=84=9C=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 | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 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 9051b7942c..3af7c6ec66 100644 --- a/jdbc/src/main/java/org/springframework/jdbc/core/JdbcTemplate.java +++ b/jdbc/src/main/java/org/springframework/jdbc/core/JdbcTemplate.java @@ -23,6 +23,14 @@ public JdbcTemplate(final DataSource dataSource) { this.dataSource = dataSource; } + public T queryForObject(final String sql, final RowMapper rowMapper, final Object... args) { + List results = query(sql, rowMapper, args); + if (results.isEmpty()) { + throw new EmptyResultAccessException(); + } + return results.get(0); + } + public List query(final String sql, final RowMapper rowMapper, final Object... args) { try (Connection conn = dataSource.getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { @@ -43,17 +51,9 @@ public List query(final String sql, final RowMapper rowMapper, final O } } - public T queryForObject(final String sql, final RowMapper rowMapper, final Object... args) { - List results = query(sql, rowMapper, args); - if (results.isEmpty()) { - throw new EmptyResultAccessException(); - } - return results.get(0); - } - public void update(final String sql, final Object... args) { try (Connection conn = dataSource.getConnection(); - PreparedStatement pstmt = conn.prepareStatement(sql)) { + PreparedStatement pstmt = conn.prepareStatement(sql)) { log.debug("query : {}", sql); PreparedStatementSetter pstSetter = new ArgumentPreparedStatementSetter(args); From c27f5273ac73cce68713e7ffe03200ea9710edc5 Mon Sep 17 00:00:00 2001 From: aak2075 Date: Sun, 1 Oct 2023 11:27:47 +0900 Subject: [PATCH 3/3] =?UTF-8?q?refactor:=20rowNum=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/java/com/techcourse/dao/UserDao.java | 2 +- .../main/java/org/springframework/jdbc/core/JdbcTemplate.java | 3 +-- .../src/main/java/org/springframework/jdbc/core/RowMapper.java | 2 +- 3 files changed, 3 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 57cb0f618c..7161299cac 100644 --- a/app/src/main/java/com/techcourse/dao/UserDao.java +++ b/app/src/main/java/com/techcourse/dao/UserDao.java @@ -15,7 +15,7 @@ public class UserDao { private final JdbcTemplate jdbcTemplate; - private RowMapper rowMapper = (rs, rowNum) -> { + private RowMapper rowMapper = rs -> { Long id = rs.getLong("id"); String account = rs.getString("account"); String password = rs.getString("password"); 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 3af7c6ec66..c318dc5e01 100644 --- a/jdbc/src/main/java/org/springframework/jdbc/core/JdbcTemplate.java +++ b/jdbc/src/main/java/org/springframework/jdbc/core/JdbcTemplate.java @@ -41,9 +41,8 @@ public List query(final String sql, final RowMapper rowMapper, final O ResultSet resultSet = pstmt.executeQuery(); List results = new ArrayList<>(); - int rowNum = 0; while (resultSet.next()) { - results.add(rowMapper.mapRow(resultSet, rowNum++)); + results.add(rowMapper.mapRow(resultSet)); } return results; } catch (SQLException e) { diff --git a/jdbc/src/main/java/org/springframework/jdbc/core/RowMapper.java b/jdbc/src/main/java/org/springframework/jdbc/core/RowMapper.java index b1d56e4b25..a264f57230 100644 --- a/jdbc/src/main/java/org/springframework/jdbc/core/RowMapper.java +++ b/jdbc/src/main/java/org/springframework/jdbc/core/RowMapper.java @@ -6,5 +6,5 @@ @FunctionalInterface public interface RowMapper { - T mapRow(ResultSet rs, int rowNum) throws SQLException; + T mapRow(ResultSet rs) throws SQLException; }