Skip to content

Commit

Permalink
[JDBC 라이브러리 구현하기 - 3,4단계] 에코(조은찬) 미션 제출합니다. (#548)
Browse files Browse the repository at this point in the history
* refactor: update에 가변인자를 받는 메서드 추가 및 try-with-resources 사용

* refactor: Callback과 ResultSetExtractor을 이용해 try-with-resources 구문 분리

* feat: Transaction 경계 구현

* refactor: 서비스에서 트랜젝션 구현을 위해 Connection 파라미터 추가

* feat: TransactionSynchronizationManager 및 DataSourceUtils 사용

* refactor: DataSourceUtils 사용으로 불필요한 Connection parameter 제거

* refactor: 트랜젝션 서비스 추상화

* refactor: 리뷰 반영

* refactor: 불필요한 getConnection 메서드 제거

* refactor: JdbcTemplate 메서드 정리

* refactor: 인프라 코드 제거

* fix: UserService 수정
  • Loading branch information
echo724 authored Oct 11, 2023
1 parent a5fd0e4 commit 20ffa66
Show file tree
Hide file tree
Showing 13 changed files with 207 additions and 137 deletions.
8 changes: 3 additions & 5 deletions app/src/main/java/com/techcourse/dao/UserDao.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,20 +46,18 @@ public void update(final User user) {

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

public User findById(final Long id) {
final var sql = "select id, account, password, email from users where id = ?";
final PreparedStatementSetter preparedStatementSetter = pstmt -> pstmt.setLong(1, id);
return jdbcTemplate.query(sql, USER_ROW_MAPPER, preparedStatementSetter);

return jdbcTemplate.queryForObject(sql, USER_ROW_MAPPER, preparedStatementSetter);
}


public User findByAccount(final String account) {
final var sql = "select id, account, password, email from users where account = ?";
final PreparedStatementSetter preparedStatementSetter = pstmt -> pstmt.setString(1, account);
return jdbcTemplate.query(sql, USER_ROW_MAPPER, preparedStatementSetter);
return jdbcTemplate.queryForObject(sql, USER_ROW_MAPPER, account);
}
}
45 changes: 6 additions & 39 deletions app/src/main/java/com/techcourse/dao/UserHistoryDao.java
Original file line number Diff line number Diff line change
@@ -1,62 +1,29 @@
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;

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

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);

final String sql = "insert into user_history (user_id, account, password, email, created_at, created_by) values (?, ?, ?, ?, ?, ?)";
jdbcTemplate.update(sql, pstmt -> {
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) {}
}
});
}
}
36 changes: 36 additions & 0 deletions app/src/main/java/com/techcourse/service/AppUserService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.techcourse.service;

import com.techcourse.dao.UserDao;
import com.techcourse.dao.UserHistoryDao;
import com.techcourse.domain.User;
import com.techcourse.domain.UserHistory;
import org.springframework.dao.DataAccessException;

public class AppUserService implements UserService {

private final UserDao userDao;
private final UserHistoryDao userHistoryDao;

public AppUserService(final UserDao userDao, final UserHistoryDao userHistoryDao) {
this.userDao = userDao;
this.userHistoryDao = userHistoryDao;
}

@Override
public void insert(final User user) {
userDao.insert(user);
}

@Override
public void changePassword(final long id, final String newPassword, final String createBy) throws DataAccessException {
final var user = findById(id);
user.changePassword(newPassword);
userDao.update(user);
userHistoryDao.log(new UserHistory(user, createBy));
}

@Override
public User findById(final long id) {
return userDao.findById(id);
}
}
46 changes: 46 additions & 0 deletions app/src/main/java/com/techcourse/service/TxUserService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.techcourse.service;

import com.techcourse.config.DataSourceConfig;
import com.techcourse.domain.User;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.datasource.DataSourceUtils;

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

public class TxUserService implements UserService {
private final UserService userService;

public TxUserService(final UserService userService) {
this.userService = userService;
}

@Override
public User findById(final long id) {
return userService.findById(id);
}

@Override
public void insert(final User user) {
userService.insert(user);
}

@Override
public void changePassword(final long id, final String newPassword, final String createBy) {
final Connection connection = DataSourceUtils.getConnection(DataSourceConfig.getInstance());
try {
connection.setAutoCommit(false);
userService.changePassword(id, newPassword, createBy);
connection.commit();
} catch (final Exception e) {
try {
connection.rollback();
} catch (SQLException ex) {
throw new DataAccessException(ex);
}
throw new DataAccessException(e);
} finally {
DataSourceUtils.releaseConnection(connection, DataSourceConfig.getInstance());
}
}
}
29 changes: 4 additions & 25 deletions app/src/main/java/com/techcourse/service/UserService.java
Original file line number Diff line number Diff line change
@@ -1,32 +1,11 @@
package com.techcourse.service;

import com.techcourse.dao.UserDao;
import com.techcourse.dao.UserHistoryDao;
import com.techcourse.domain.User;
import com.techcourse.domain.UserHistory;

public class UserService {
public interface UserService {
User findById(final long id);

private final UserDao userDao;
private final UserHistoryDao userHistoryDao;
void insert(User user);

public UserService(final UserDao userDao, final UserHistoryDao userHistoryDao) {
this.userDao = userDao;
this.userHistoryDao = userHistoryDao;
}

public User findById(final long id) {
return userDao.findById(id);
}

public void insert(final User user) {
userDao.insert(user);
}

public void changePassword(final long id, final String newPassword, final String createBy) {
final var user = findById(id);
user.changePassword(newPassword);
userDao.update(user);
userHistoryDao.log(new UserHistory(user, createBy));
}
void changePassword(long id, String newPassword, String createBy);
}
4 changes: 2 additions & 2 deletions app/src/test/java/com/techcourse/dao/UserDaoTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@

class UserDaoTest {

private final JdbcTemplate jdbcTemplate = new JdbcTemplate(DataSourceConfig.getInstance());
private UserDao userDao;

@BeforeEach
void setup() {
DatabasePopulatorUtils.execute(DataSourceConfig.getInstance());

userDao = new UserDao(new JdbcTemplate(DataSourceConfig.getInstance()));
userDao = new UserDao(jdbcTemplate);
final var user = new User("gugu", "password", "[email protected]");
userDao.insert(user);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,15 @@
import com.techcourse.dao.UserHistoryDao;
import com.techcourse.domain.User;
import com.techcourse.support.jdbc.init.DatabasePopulatorUtils;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;

@Disabled
class UserServiceTest {
class AppUserServiceTest {

private JdbcTemplate jdbcTemplate;
private UserDao userDao;
Expand All @@ -33,7 +31,7 @@ void setUp() {
@Test
void testChangePassword() {
final var userHistoryDao = new UserHistoryDao(jdbcTemplate);
final var userService = new UserService(userDao, userHistoryDao);
final var userService = new AppUserService(userDao, userHistoryDao);

final var newPassword = "qqqqq";
final var createBy = "gugu";
Expand All @@ -48,7 +46,10 @@ void testChangePassword() {
void testTransactionRollback() {
// 트랜잭션 롤백 테스트를 위해 mock으로 교체
final var userHistoryDao = new MockUserHistoryDao(jdbcTemplate);
final var userService = new UserService(userDao, userHistoryDao);
// 애플리케이션 서비스
final var appUserService = new AppUserService(userDao, userHistoryDao);
// 트랜잭션 서비스 추상화
final var userService = new TxUserService(appUserService);

final var newPassword = "newPassword";
final var createBy = "gugu";
Expand Down
Loading

0 comments on commit 20ffa66

Please sign in to comment.