From 37ae7873aef867e3397a08552718f22c18ce15c6 Mon Sep 17 00:00:00 2001 From: somin <70891072+somsom13@users.noreply.github.com> Date: Sun, 1 Oct 2023 14:27:26 +0900 Subject: [PATCH] =?UTF-8?q?[JDBC=20=EB=9D=BC=EC=9D=B4=EB=B8=8C=EB=9F=AC?= =?UTF-8?q?=EB=A6=AC=20=EA=B5=AC=ED=98=84=ED=95=98=EA=B8=B0=20-=201?= =?UTF-8?q?=EB=8B=A8=EA=B3=84]=20=EB=B0=94=EB=A1=A0(=EC=9D=B4=EC=86=8C?= =?UTF-8?q?=EB=AF=BC)=20=EB=AF=B8=EC=85=98=20=EC=A0=9C=EC=B6=9C=ED=95=A9?= =?UTF-8?q?=EB=8B=88=EB=8B=A4.=20(#305)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 패키지 위치 변경 및 코드 정리 * feat: JdbcTemplate update, query 메서드 구현 * feat: UserDao 추가 기능 구현 * refactor: UserDao DataSource 제거 * feat: UserDao 투두 로직 구현 --------- Co-authored-by: kang-hyungu --- README.md | 5 + .../main/java/com/techcourse/dao/UserDao.java | 116 ++++-------------- .../java/com/techcourse/dao/UserDaoTest.java | 3 +- .../jdbc/core/JdbcTemplate.java | 66 +++++++++- .../springframework/jdbc/core/RowMapper.java | 10 ++ .../java/aop/config/DataSourceConfig.java | 1 + study/src/main/resources/application.yml | 1 + 7 files changed, 107 insertions(+), 95 deletions(-) create mode 100644 jdbc/src/main/java/org/springframework/jdbc/core/RowMapper.java diff --git a/README.md b/README.md index 721b81d472..1bf0b8f2a0 100644 --- a/README.md +++ b/README.md @@ -1 +1,6 @@ # JDBC 라이브러리 구현하기 + +### 1단계 +- [x] JdbcTemplate insert, update, delete, select 쿼리 메서드 구현 + - [x] UserDao rowmapper 구현 +- [x] UserDao todo 쿼리 로직 구현 diff --git a/app/src/main/java/com/techcourse/dao/UserDao.java b/app/src/main/java/com/techcourse/dao/UserDao.java index d14c545f34..93a6e9c1e8 100644 --- a/app/src/main/java/com/techcourse/dao/UserDao.java +++ b/app/src/main/java/com/techcourse/dao/UserDao.java @@ -1,121 +1,53 @@ package com.techcourse.dao; import com.techcourse.domain.User; -import org.springframework.jdbc.core.JdbcTemplate; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.sql.DataSource; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; import java.util.List; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; public class UserDao { - private static final Logger log = LoggerFactory.getLogger(UserDao.class); - - private final DataSource dataSource; + private static final RowMapper ROW_MAPPER = (rs, count) -> + new User( + rs.getLong("id"), + rs.getString("account"), + rs.getString("password"), + rs.getString("email") + ); - public UserDao(final DataSource dataSource) { - this.dataSource = dataSource; - } + private final JdbcTemplate jdbcTemplate; 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) {} + final String sql = "insert into users (account, password, email) values (?, ?, ?)"; - 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 String 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 String sql = "select id, account, email, password from users"; + + return jdbcTemplate.query(sql, ROW_MAPPER); } 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); + final String sql = "select id, account, password, email from users where id = ?"; - 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, ROW_MAPPER, id); } public User findByAccount(final String account) { - // todo - return null; + final String sql = "select id, account, password, email from users where account = ?"; + + return jdbcTemplate.queryForObject(sql, ROW_MAPPER, 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..7e9cc2b01a 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; @@ -16,7 +17,7 @@ class UserDaoTest { void setup() { DatabasePopulatorUtils.execute(DataSourceConfig.getInstance()); - userDao = new UserDao(DataSourceConfig.getInstance()); + userDao = new UserDao(new JdbcTemplate(DataSourceConfig.getInstance())); final var user = new User("gugu", "password", "hkkang@woowahan.com"); userDao.insert(user); } 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..db77bd4d70 100644 --- a/jdbc/src/main/java/org/springframework/jdbc/core/JdbcTemplate.java +++ b/jdbc/src/main/java/org/springframework/jdbc/core/JdbcTemplate.java @@ -1,10 +1,15 @@ package org.springframework.jdbc.core; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; +import javax.sql.DataSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.sql.DataSource; - public class JdbcTemplate { private static final Logger log = LoggerFactory.getLogger(JdbcTemplate.class); @@ -14,4 +19,61 @@ public class JdbcTemplate { public JdbcTemplate(final DataSource dataSource) { this.dataSource = dataSource; } + + public List query(final String sql, final RowMapper rowMapper, final Object... args) { + try (final Connection connection = dataSource.getConnection(); + final PreparedStatement pstmt = connection.prepareStatement(sql)) { + log.debug("query : {}", sql); + + setParamsToPreparedStatement(pstmt, args); + + final ResultSet resultSet = pstmt.executeQuery(); + final List results = new ArrayList<>(); + if (resultSet.next()) { + results.add(rowMapper.mapRow(resultSet, resultSet.getRow())); + } + + return results; + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + + private void setParamsToPreparedStatement(final PreparedStatement pstmt, final Object[] args) + throws SQLException + { + for (int i = 0; i < args.length; i++) { + pstmt.setObject(i + 1, args[i]); + } + } + + public T queryForObject(final String sql, final RowMapper rowMapper, final Object... args) { + try (final Connection connection = dataSource.getConnection(); + final PreparedStatement pstmt = connection.prepareStatement(sql)) { + log.debug("query : {}", sql); + + setParamsToPreparedStatement(pstmt, args); + + final ResultSet resultSet = pstmt.executeQuery(); + if (resultSet.next()) { + return rowMapper.mapRow(resultSet, resultSet.getRow()); + } + return null; + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + + public int update(final String sql, final Object... args) { + try (final Connection connection = dataSource.getConnection(); + final PreparedStatement pstmt = connection.prepareStatement(sql)) { + log.debug("query : {}", sql); + + setParamsToPreparedStatement(pstmt, args); + + return pstmt.executeUpdate(); + } catch (SQLException e) { + throw new RuntimeException(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 new file mode 100644 index 0000000000..ecb98ccd47 --- /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(final ResultSet resultSet, final int count) throws SQLException; +} diff --git a/study/src/main/java/aop/config/DataSourceConfig.java b/study/src/main/java/aop/config/DataSourceConfig.java index b27245b932..d64fc2ca2b 100644 --- a/study/src/main/java/aop/config/DataSourceConfig.java +++ b/study/src/main/java/aop/config/DataSourceConfig.java @@ -14,6 +14,7 @@ public class DataSourceConfig { public DataSource dataSource() { return new EmbeddedDatabaseBuilder() .setType(EmbeddedDatabaseType.H2) + .setName("test;DB_CLOSE_DELAY=-1;MODE=MYSQL;") .addScript("classpath:schema.sql") .build(); } diff --git a/study/src/main/resources/application.yml b/study/src/main/resources/application.yml index 84c31c77b5..b9451e1013 100644 --- a/study/src/main/resources/application.yml +++ b/study/src/main/resources/application.yml @@ -1,5 +1,6 @@ spring: jpa: + open-in-view: false show-sql: true generate-ddl: true hibernate: