Skip to content

Commit

Permalink
[JDBC 라이브러리 구현하기 - 2단계] 이리내(성채연) 미션 제출합니다. (#391)
Browse files Browse the repository at this point in the history
이리내 안녕하세요! 리뷰가 좀 늦었죠..ㅠㅠ 중복 코드를 제거하려는 노력이 보이는 코드였네요..! 꼼꼼한 테스트까지 굳인데요? 제 의견은 참고만 해주시면 감사하겠습니다! 가독성면에서의 리팩토링은 이리내의 선택이지만 예외처리에 대한 부분은 한번 더 고민해 봐주시면 좋을것 같아요! 이미 훌륭한 코드지만! 고생 많으셨습니다~!
  • Loading branch information
hectick authored Oct 6, 2023
1 parent a3e9fd7 commit 266190f
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 71 deletions.
12 changes: 6 additions & 6 deletions app/src/main/java/com/techcourse/dao/UserDao.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@

public class UserDao {

private final JdbcTemplate jdbcTemplate;

private final RowMapper<User> rowMapper = rs ->
private static final RowMapper<User> ROW_MAPPER = rs ->
new User(
rs.getLong("id"),
rs.getString("account"),
rs.getString("password"),
rs.getString("email")
);

private final JdbcTemplate jdbcTemplate;

public UserDao(final DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
Expand All @@ -38,16 +38,16 @@ public void update(final User user) {

public List<User> findAll() {
final String sql = "select id, account, password, email from users";
return jdbcTemplate.query(sql, rowMapper);
return jdbcTemplate.query(sql, ROW_MAPPER);
}

public User findById(final Long id) {
final String sql = "select id, account, password, email from users where id = ?";
return jdbcTemplate.queryForObject(sql, rowMapper, id);
return jdbcTemplate.queryForObject(sql, ROW_MAPPER, id);
}

public User findByAccount(final String account) {
final String sql = "select id, account, password, email from users where account = ?";
return jdbcTemplate.queryForObject(sql, rowMapper, account);
return jdbcTemplate.queryForObject(sql, ROW_MAPPER, account);
}
}
56 changes: 13 additions & 43 deletions app/src/main/java/com/techcourse/dao/UserHistoryDao.java
Original file line number Diff line number Diff line change
@@ -1,62 +1,32 @@
package com.techcourse.dao;

import com.techcourse.domain.UserHistory;
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.SQLException;
import org.springframework.jdbc.core.JdbcTemplate;

public class UserHistoryDao {

private static final Logger log = LoggerFactory.getLogger(UserHistoryDao.class);

private final DataSource dataSource;
private final JdbcTemplate jdbcTemplate;

public UserHistoryDao(final DataSource dataSource) {
this.dataSource = dataSource;
this.jdbcTemplate = new JdbcTemplate(dataSource);
}

public UserHistoryDao(final JdbcTemplate jdbcTemplate) {
this.dataSource = null;
this.jdbcTemplate = jdbcTemplate;
}

public void log(final UserHistory userHistory) {
final var sql = "insert into user_history (user_id, account, password, email, created_at, created_by) values (?, ?, ?, ?, ?, ?)";

Connection conn = null;
PreparedStatement pstmt = null;
try {
conn = dataSource.getConnection();
pstmt = conn.prepareStatement(sql);

log.debug("query : {}", sql);

pstmt.setLong(1, userHistory.getUserId());
pstmt.setString(2, userHistory.getAccount());
pstmt.setString(3, userHistory.getPassword());
pstmt.setString(4, userHistory.getEmail());
pstmt.setObject(5, userHistory.getCreatedAt());
pstmt.setString(6, userHistory.getCreateBy());
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,
userHistory.getUserId(),
userHistory.getAccount(),
userHistory.getPassword(),
userHistory.getEmail(),
userHistory.getCreatedAt(),
userHistory.getCreateBy()
);
}
}
25 changes: 25 additions & 0 deletions app/src/test/java/com/techcourse/dao/UserHistoryDaoTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.techcourse.dao;

import static org.assertj.core.api.Assertions.assertThatCode;

import com.techcourse.config.DataSourceConfig;
import com.techcourse.domain.User;
import com.techcourse.domain.UserHistory;
import com.techcourse.support.jdbc.init.DatabasePopulatorUtils;
import org.junit.jupiter.api.Test;

class UserHistoryDaoTest {

private UserHistoryDao userHistoryDao;

@Test
void log() {
DatabasePopulatorUtils.execute(DataSourceConfig.getInstance());

userHistoryDao = new UserHistoryDao(DataSourceConfig.getInstance());
final User user = new User(1L, "irene", "password", "[email protected]");
final UserHistory userHistory = new UserHistory(user, "irene");

assertThatCode(() -> userHistoryDao.log(userHistory)).doesNotThrowAnyException();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.springframework.jdbc.core;

import java.sql.PreparedStatement;
import java.sql.SQLException;

@FunctionalInterface
public interface ExecutionCallback<T> {

T execute(final PreparedStatement preparedStatement) throws SQLException;
}
51 changes: 29 additions & 22 deletions jdbc/src/main/java/org/springframework/jdbc/core/JdbcTemplate.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,50 +19,57 @@ public JdbcTemplate(final DataSource dataSource) {
}

public int update(final String sql, final Object... args) {
return execute(connection -> prepareStatement(sql, connection, args), PreparedStatement::executeUpdate);
}

private <T> T execute(final PreparedStatementCallback preparedStatementCallback,
final ExecutionCallback<T> executionCallback) {
try (final Connection connection = dataSource.getConnection();
final PreparedStatement pstmt = connection.prepareStatement(sql)) {
setParameters(pstmt, args);
return pstmt.executeUpdate();
final PreparedStatement pstmt = preparedStatementCallback.prepareStatement(connection)) {
return executionCallback.execute(pstmt);
} catch (SQLException e) {
throw new DataAccessException(e);
}
}

public void setParameters(final PreparedStatement pstmt, final Object... args) throws SQLException {
private PreparedStatement prepareStatement(final String sql, final Connection connection, final Object[] args)
throws SQLException {
final PreparedStatement pstmt = connection.prepareStatement(sql);
setParameters(pstmt, args);
return pstmt;
}

private void setParameters(final PreparedStatement pstmt, final Object[] args) throws SQLException {
for (int i = 0; i < args.length; i++) {
pstmt.setObject(i + 1, args[i]);
}
}

@Nullable
public <T> T queryForObject(final String sql, final RowMapper<T> rowMapper, final Object... args) {
try (final Connection connection = dataSource.getConnection();
final PreparedStatement pstmt = connection.prepareStatement(sql)) {
setParameters(pstmt, args);
try (final ResultSet rs = pstmt.executeQuery()) {
if (rs.next()) {
return rowMapper.mapRow(rs);
}
return null;
}
} catch (SQLException e) {
throw new DataAccessException(e);
final List<T> results = executeQuery(connection -> prepareStatement(sql, connection, args), rowMapper);
if (results.isEmpty()) {
return null;
}
return results.get(0);
}

public <T> List<T> query(final String sql, final RowMapper<T> rowMapper, final Object... args) {
try (final Connection connection = dataSource.getConnection();
final PreparedStatement pstmt = connection.prepareStatement(sql)) {
setParameters(pstmt, args);
private <T> List<T> executeQuery(
final PreparedStatementCallback preparedStatementCallback,
final RowMapper<T> rowMapper
) {
return execute(preparedStatementCallback, pstmt -> {
try (final ResultSet rs = pstmt.executeQuery()) {
List<T> results = new ArrayList<>();
while (rs.next()) {
results.add(rowMapper.mapRow(rs));
}
return results;
}
} catch (SQLException e) {
throw new DataAccessException(e);
}
});
}

public <T> List<T> query(final String sql, final RowMapper<T> rowMapper, final Object... args) {
return executeQuery(connection -> prepareStatement(sql, connection, args), rowMapper);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.springframework.jdbc.core;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

@FunctionalInterface
public interface PreparedStatementCallback {

PreparedStatement prepareStatement(final Connection connection) throws SQLException;
}

0 comments on commit 266190f

Please sign in to comment.