Skip to content

Commit

Permalink
[JDBC 라이브러리 구현하기 - 4단계] 조이(김성연) 미션 제출합니다. (#573)
Browse files Browse the repository at this point in the history
* refactor: Transaction synchronization 적용

* refactor: 불필요 코드 제거

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

* refactor: 컨벤션 통일

* fix: TransactionManager에서 RuntimeException 시 rollback 처리하도록 변경

* refactor: TransactionSynchronizationManager resources 초기화 로직 추가
  • Loading branch information
yeonkkk authored Oct 10, 2023
1 parent 9ac44b6 commit 12c53ed
Show file tree
Hide file tree
Showing 17 changed files with 174 additions and 222 deletions.
43 changes: 2 additions & 41 deletions app/src/main/java/com/techcourse/dao/UserDao.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.techcourse.dao;

import com.techcourse.domain.User;
import java.sql.Connection;
import java.util.List;
import java.util.NoSuchElementException;
import javax.sql.DataSource;
Expand All @@ -14,15 +13,15 @@ public class UserDao {

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

private final JdbcTemplate jdbcTemplate;

private static final RowMapper<User> userRowMapper = (resultSet, rowNum) -> new User(
resultSet.getLong("id"),
resultSet.getString("account"),
resultSet.getString("password"),
resultSet.getString("email")
);

private final JdbcTemplate jdbcTemplate;

public UserDao(final DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
Expand All @@ -36,63 +35,25 @@ public void insert(final User user) {
jdbcTemplate.update(sql, user.getAccount(), user.getPassword(), user.getEmail());
}

public void insert(final Connection connection, final User user) {
final String sql = "insert into users (account, password, email) values (?, ?, ?)";
jdbcTemplate.update(connection,
sql,
user.getAccount(), user.getPassword(), user.getEmail());
}

public void update(final User user) {
final String sql = "update users set account = ?, password =?, email = ? where id = ?";
jdbcTemplate.update(sql, user.getAccount(), user.getPassword(), user.getEmail(), user.getId());
}

public void update(final Connection connection, final User user) {
final String sql = "update users set account = ?, password =?, email = ? where id = ?";
jdbcTemplate.update(connection,
sql,
user.getAccount(), user.getPassword(), user.getEmail(), user.getId());
}

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

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

public User findById(final Long id) {
final String sql = "select id, account, password, email from users where id = ?";
return jdbcTemplate.queryForObject(sql, userRowMapper, id)
.orElseThrow(() -> new NoSuchElementException("id에 해당하는 user가 없습니다."));
}

public User findById(final Connection connection, final Long id) {
final String sql = "select id, account, password, email from users where id = ?";
return jdbcTemplate.queryForObject(connection,
sql,
userRowMapper,
id)
.orElseThrow(() -> new NoSuchElementException("id에 해당하는 user가 없습니다."));
}

public User findByAccount(final String account) {
final String sql = "select id, account, password, email from users where account = ?";
return jdbcTemplate.queryForObject(sql, userRowMapper, account)
.orElseThrow(() -> new NoSuchElementException("account에 해당하는 user가 없습니다."));
}

public User findByAccount(final Connection connection, final String account) {
final String sql = "select id, account, password, email from users where account = ?";
return jdbcTemplate.queryForObject(connection,
sql,
userRowMapper, account)
.orElseThrow(() -> new NoSuchElementException("account에 해당하는 user가 없습니다."));
}
}
14 changes: 0 additions & 14 deletions app/src/main/java/com/techcourse/dao/UserHistoryDao.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.techcourse.dao;

import com.techcourse.domain.UserHistory;
import java.sql.Connection;
import javax.sql.DataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -32,17 +31,4 @@ public void log(final UserHistory userHistory) {
userHistory.getCreateBy()
);
}

public void log(final Connection connection, final UserHistory userHistory) {
final String sql = "insert into user_history (user_id, account, password, email, created_at, created_by) values (?, ?, ?, ?, ?, ?)";
jdbcTemplate.update(connection,
sql,
userHistory.getUserId(),
userHistory.getAccount(),
userHistory.getPassword(),
userHistory.getEmail(),
userHistory.getCreatedAt(),
userHistory.getCreateBy()
);
}
}
37 changes: 37 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,37 @@
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 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 User findById(final long id) {
return userDao.findById(id);
}

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

@Override
public void changePassword(final long id,
final String newPassword,
final String createBy) {
final User user = userDao.findById(id);
user.changePassword(newPassword);
userDao.update(user);
userHistoryDao.log(new UserHistory(user, createBy));
}
}
43 changes: 43 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,43 @@
package com.techcourse.service;

import com.techcourse.domain.User;
import org.springframework.transaction.TransactionManager;

public class TxUserService implements UserService {

private final UserService userService;
private final TransactionManager transactionManager;

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

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

@Override
public void insert(final User user) {
transactionManager.execute(
() -> {
userService.insert(user);
return null;
});
}

@Override
public void changePassword(final long id,
final String newPassword,
final String createBy) {
transactionManager.execute(
() -> {
userService.changePassword(id, newPassword, createBy);
return null;
}
);
}
}
39 changes: 4 additions & 35 deletions app/src/main/java/com/techcourse/service/UserService.java
Original file line number Diff line number Diff line change
@@ -1,43 +1,12 @@
package com.techcourse.service;

import com.techcourse.config.DataSourceConfig;
import com.techcourse.dao.UserDao;
import com.techcourse.dao.UserHistoryDao;
import com.techcourse.domain.User;
import com.techcourse.domain.UserHistory;
import org.springframework.transaction.TransactionManager;

public class UserService {
public interface UserService {

private final UserDao userDao;
private final UserHistoryDao userHistoryDao;
private final TransactionManager transactionManager;
User findById(final long id);

public UserService(final UserDao userDao, final UserHistoryDao userHistoryDao) {
this.userDao = userDao;
this.userHistoryDao = userHistoryDao;
this.transactionManager = new TransactionManager(DataSourceConfig.getInstance());
}
void insert(final User user);

public User findById(final long id) {
return transactionManager.execute(connection -> userDao.findById(connection, id));
}

public void insert(final User user) {
transactionManager.execute(connection -> {
userDao.insert(connection, user);
return null;
});
}

public void changePassword(final long id, final String newPassword, final String createBy) {
transactionManager.execute(connection -> {
final var user = userDao.findById(connection, id);
user.changePassword(newPassword);
userDao.update(connection, user);
userHistoryDao.log(connection, new UserHistory(user, createBy));
return null;
}
);
}
void changePassword(final long id, final String newPassword, final String createBy);
}
36 changes: 15 additions & 21 deletions app/src/test/java/com/techcourse/dao/UserDaoTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
import com.techcourse.config.DataSourceConfig;
import com.techcourse.domain.User;
import com.techcourse.support.jdbc.init.DatabasePopulatorUtils;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.NoSuchElementException;
import javax.sql.DataSource;
import org.junit.jupiter.api.BeforeEach;
Expand All @@ -30,56 +28,52 @@ class UserDaoTest {

private final DataSource dataSource = DataSourceConfig.getInstance();

private Connection connection;

@BeforeEach
void setup() throws SQLException {
connection = dataSource.getConnection();

JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
jdbcTemplate.execute(connection, INIT_USER_TABLE_SQL);
void setup() {
final JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
jdbcTemplate.execute(INIT_USER_TABLE_SQL);

DatabasePopulatorUtils.execute(dataSource);
userDao = new UserDao(dataSource);

final var user = new User("gugu", "password", "[email protected]");
userDao.insert(connection, user);
final User user = new User("gugu", "password", "[email protected]");
userDao.insert(user);
}

@Test
void findAll() {
final var users = userDao.findAll(connection);
final var users = userDao.findAll();

assertThat(users).isNotEmpty();
}

@Test
void findById() {
final var user = userDao.findById(connection, 1L);
final var user = userDao.findById(1L);

assertThat(user.getAccount()).isEqualTo("gugu");
}

@Test
void findById_fail() {
assertThatThrownBy(
() -> userDao.findById(connection, -1L)
() -> userDao.findById(-1L)
).isInstanceOf(NoSuchElementException.class)
.hasMessage("id에 해당하는 user가 없습니다.");
}

@Test
void findByAccount() {
final var account = "gugu";
final var user = userDao.findByAccount(connection, account);
final var user = userDao.findByAccount(account);

assertThat(user.getAccount()).isEqualTo(account);
}

@Test
void findByAccount_fail() {
assertThatThrownBy(
() -> userDao.findByAccount(connection, "joy")
() -> userDao.findByAccount("joy")
).isInstanceOf(NoSuchElementException.class)
.hasMessage("account에 해당하는 user가 없습니다.");
}
Expand All @@ -88,22 +82,22 @@ void findByAccount_fail() {
void insert() {
final var account = "insert-gugu";
final var user = new User(account, "password", "[email protected]");
userDao.insert(connection, user);
userDao.insert(user);

final var actual = userDao.findById(connection, 2L);
final var actual = userDao.findById(2L);

assertThat(actual.getAccount()).isEqualTo(account);
}

@Test
void update() {
final var newPassword = "password99";
final var user = userDao.findById(connection, 1L);
final var user = userDao.findById(1L);
user.changePassword(newPassword);

userDao.update(connection, user);
userDao.update(user);

final var actual = userDao.findById(connection, 1L);
final var actual = userDao.findById(1L);

assertThat(actual.getPassword()).isEqualTo(newPassword);
}
Expand Down
16 changes: 2 additions & 14 deletions app/src/test/java/com/techcourse/dao/UserHistoryDaoTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,13 @@
import com.techcourse.config.DataSourceConfig;
import com.techcourse.domain.UserHistory;
import com.techcourse.support.jdbc.init.DatabasePopulatorUtils;
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

class UserHistoryDaoTest {

public static final UserHistory USER_HISTORY = new UserHistory(1L,
private static final UserHistory USER_HISTORY = new UserHistory(1L,
1L,
"joy",
"joy1234",
Expand All @@ -22,15 +20,12 @@ class UserHistoryDaoTest {

private final DataSource dataSource = DataSourceConfig.getInstance();

private Connection connection;

private UserHistoryDao userHistoryDao;

@BeforeEach
void setUp() throws SQLException {
void setUp() {
DatabasePopulatorUtils.execute(dataSource);
userHistoryDao = new UserHistoryDao(dataSource);
connection = dataSource.getConnection();
}

@Test
Expand All @@ -39,11 +34,4 @@ void log() {
() -> userHistoryDao.log(USER_HISTORY)
);
}

@Test
void connection_log() {
assertDoesNotThrow(
() -> userHistoryDao.log(connection, USER_HISTORY)
);
}
}
Loading

0 comments on commit 12c53ed

Please sign in to comment.