Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[JDBC 라이브러리 구현하기 - 4단계] 쥬니(전정준) 미션 제출합니다. #516

Merged
merged 9 commits into from
Oct 10, 2023
9 changes: 4 additions & 5 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 javax.sql.DataSource;
import org.slf4j.Logger;
Expand Down Expand Up @@ -30,20 +29,20 @@ public UserDao(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}

public void insert(Connection connection, User user) {
public void insert(User user) {
String sql = "insert into users (account, password, email) values (?, ?, ?)";

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

jdbcTemplate.update(connection, sql, user.getAccount(), user.getPassword(), user.getEmail());
jdbcTemplate.update(sql, user.getAccount(), user.getPassword(), user.getEmail());
}

public void update(Connection connection, User user) {
public void update(User user) {
String sql = "UPDATE users SET account = ?, password = ?, email = ? WHERE id = ?";

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

jdbcTemplate.update(connection, sql, user.getAccount(), user.getPassword(), user.getEmail(), user.getId());
jdbcTemplate.update(sql, user.getAccount(), user.getPassword(), user.getEmail(), user.getId());
}

public List<User> findAll() {
Expand Down
5 changes: 2 additions & 3 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.springframework.jdbc.core.JdbcTemplate;

Expand All @@ -17,10 +16,10 @@ public UserHistoryDao(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}

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

jdbcTemplate.update(connection, sql, userHistory.getUserId(), userHistory.getAccount(),
jdbcTemplate.update(sql, userHistory.getUserId(), userHistory.getAccount(),
userHistory.getPassword(), userHistory.getEmail(), userHistory.getCreatedAt(),
userHistory.getCreateBy());
}
Expand Down
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(UserDao userDao, UserHistoryDao userHistoryDao) {
this.userDao = userDao;
this.userHistoryDao = userHistoryDao;
}

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

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

@Override
public void changePassword(long id, String newPassword, String createBy) {
User user = findById(id);
user.changePassword(newPassword);

userDao.update(user);
userHistoryDao.log(new UserHistory(user, createBy));
}

}
48 changes: 48 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,48 @@
package com.techcourse.service;

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

public class TxUserService implements UserService {

private final TransactionManager transactionManager;
private final UserService appUserService;

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

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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P?:

이 부분은 트랜잭션 처리를 안하신 이유가 따로 있으신가요??

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 부분에 대해서 질문하실거라고 생각했어요 ㅎㅎ

조회용 트랜잭션(readOnly)을 만들기 위해서, 부가적인 기능을 구현해야한다는 점에서 귀찮음을 느꼈어요..
하지만, 빠르게 구현했습니당 ~!


@Override
public void insert(User user) {
transactionManager.start();
try {
appUserService.insert(user);

transactionManager.commit();
} catch (DataAccessException e) {
transactionManager.rollback();
throw e;
}

}

@Override
public void changePassword(long id, String newPassword, String createBy) {
transactionManager.start();
try {
appUserService.changePassword(id, newPassword, createBy);

transactionManager.commit();
} catch (DataAccessException e) {
transactionManager.rollback();
throw e;
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3:

지난 번 리뷰에서도 말씀 드렸었는데,
이부분의 try-catch 중복 제거하는 거 어떻게 생각하시나요?

지금은 Service도 몇개 안되고 그안에 메서드들도 몇개 안되지만 이게 많아지면 라이브러리 사용자가 너무 구현하기 힘들 것 같아요.
그리고 혹은 이런 라이브러리 사용자가 직접 트랜잭션을 감싸는 방법 말고,
mvc에서 사용했던 어노테이션 같은 방법으로 트랜잭션 처리하는 방법은 생각해보셨나요??

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

try-catch 중복은 제거 완료했습니다.

어노테이션 방법으로 구현해보고 싶어서, 한 시간정도 시도해보았는데요.
구현해야 할 클래스 및 기능들이 점점 많아지고.. 이게 맞나 싶어서 다 롤백했습니다 ㅠㅠ (너무 어렵기도 했어요..)
가능하시다면, 루카가 구현해서 설명해주시면 좋을 것 같아요 ㅋㅋ

}
}
54 changes: 4 additions & 50 deletions app/src/main/java/com/techcourse/service/UserService.java
Original file line number Diff line number Diff line change
@@ -1,59 +1,13 @@
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 java.sql.Connection;
import org.springframework.dao.DataAccessException;
import org.springframework.transaction.Transaction;
import org.springframework.transaction.TransactionManager;

public class UserService {
public interface UserService {

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

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

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

public void insert(User user) {
Transaction transaction = transactionManager.getTransaction();
transaction.start();

try {
userDao.insert(transaction.getConnection(), user);
transaction.commit();
} catch (DataAccessException e) {
transaction.rollback();
throw e;
}
}

public void changePassword(long id, String newPassword, String createBy) {
Transaction transaction = transactionManager.getTransaction();
transaction.start();
try {
Connection connection = transaction.getConnection();
User user = findById(id);

user.changePassword(newPassword);
userDao.update(connection, user);
userHistoryDao.log(connection, new UserHistory(user, createBy));

transaction.commit();
} catch (DataAccessException e) {
transaction.rollback();
throw e;
}
}
void changePassword(long id, String newPassword, String createBy);

}
16 changes: 7 additions & 9 deletions app/src/test/java/com/techcourse/dao/UserDaoTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,16 @@ class UserDaoTest {

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

@BeforeEach
void setup() throws SQLException {
dataSource = DataSourceConfig.getInstance();
DatabasePopulatorUtils.execute(dataSource);
DatabasePopulatorUtils.execute(DataSourceConfig.getInstance());

jdbcTemplate.update(dataSource.getConnection(), "TRUNCATE TABLE users RESTART IDENTITY");
jdbcTemplate.update("TRUNCATE TABLE users RESTART IDENTITY");
userDao = new UserDao(DataSourceConfig.getInstance());

User user = new User("gugu", "password", "[email protected]");
userDao.insert(dataSource.getConnection(), user);
userDao.insert(user);
}

@Test
Expand All @@ -42,7 +40,7 @@ void findAll() {

@Test
void findById() throws SQLException {
userDao.insert(dataSource.getConnection(), new User("gugu", "password", "[email protected]"));
userDao.insert(new User("gugu", "password", "[email protected]"));
User user = userDao.findById(1L);

assertThat(user.getAccount()).isEqualTo("gugu");
Expand All @@ -60,7 +58,7 @@ void findByAccount() {
void insert() throws SQLException {
String account = "insert-gugu";
User user = new User(account, "password", "[email protected]");
userDao.insert(dataSource.getConnection(), user);
userDao.insert(user);

User actual = userDao.findById(2L);

Expand All @@ -73,7 +71,7 @@ void update() throws SQLException {
User user = userDao.findById(1L);
user.changePassword(newPassword);

userDao.update(dataSource.getConnection(), user);
userDao.update(user);

User actual = userDao.findById(1L);

Expand All @@ -88,7 +86,7 @@ void findByAccount_FailByMultipleResults() throws SQLException {
assertThat(findUser).isNotNull();

User duplicateUser = new User("gugu", "password", "[email protected]");
userDao.insert(dataSource.getConnection(), duplicateUser);
userDao.insert(duplicateUser);

//when then
assertThatThrownBy(() -> userDao.findByAccount("gugu"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,36 +8,35 @@
import com.techcourse.dao.UserHistoryDao;
import com.techcourse.domain.User;
import com.techcourse.support.jdbc.init.DatabasePopulatorUtils;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.TransactionManager;

class UserServiceTest {
class AppUserServiceTest {

private JdbcTemplate jdbcTemplate;
private UserDao userDao;
private TransactionManager transactionManager;

@BeforeEach
void setUp() throws SQLException {
void setUp() {
DataSource dataSource = DataSourceConfig.getInstance();
this.jdbcTemplate = new JdbcTemplate(dataSource);
this.userDao = new UserDao(jdbcTemplate);
this.transactionManager = new TransactionManager(dataSource);

DatabasePopulatorUtils.execute(DataSourceConfig.getInstance());
DatabasePopulatorUtils.execute(dataSource);
final var user = new User("gugu", "password", "[email protected]");
userDao.insert(dataSource.getConnection(), user);
userDao.insert(user);
}

@Test
void testChangePassword() {
final var userHistoryDao = new UserHistoryDao(jdbcTemplate);
final var userService = new UserService(transactionManager, userDao, userHistoryDao);
final var userService = new AppUserService(userDao, userHistoryDao);

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

final var newPassword = "newPassword";
final var createBy = "gugu";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public MockUserHistoryDao(final JdbcTemplate jdbcTemplate) {
}

@Override
public void log(Connection connection, final UserHistory userHistory) {
public void log(final UserHistory userHistory) {
throw new DataAccessException();
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package org.springframework.jdbc.core;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
Expand All @@ -17,8 +16,8 @@ public JdbcTemplate(DataSource dataSource) {
this.queryTemplate = new QueryTemplate(dataSource);
}

public void update(Connection connection, String sql, Object... args) {
queryTemplate.update(connection, sql, PreparedStatement::executeUpdate, args);
public void update(String sql, Object... args) {
queryTemplate.update(sql, PreparedStatement::executeUpdate, args);
}

public <T> List<T> query(String sql, RowMapper<T> rowMapper, Object... args) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.datasource.DataSourceUtils;

public class QueryTemplate {

Expand All @@ -19,7 +20,8 @@ public QueryTemplate(DataSource dataSource) {
this.dataSource = dataSource;
}

public <T> T update(Connection connection, String sql, UpdateExecutor<T> executor, Object... args) {
public <T> T update(String sql, UpdateExecutor<T> executor, Object... args) {
Connection connection = DataSourceUtils.getConnection(dataSource);
try (PreparedStatement preparedStatement = getInitializedPreparedStatement(sql, connection, args)) {
return executor.execute(preparedStatement);
} catch (SQLException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public static Connection getConnection(DataSource dataSource) throws CannotGetJd

public static void releaseConnection(Connection connection, DataSource dataSource) {
try {
TransactionSynchronizationManager.unbindResource(dataSource);
connection.close();
} catch (SQLException ex) {
throw new CannotGetJdbcConnectionException("Failed to close JDBC Connection");
Expand Down
Loading