Skip to content

Commit

Permalink
[JDBC 라이브러리 구현하기 - 4단계] 베베(최원용) 미션 제출합니다. (#590)
Browse files Browse the repository at this point in the history
* refactor: Service 계층 분리

* refactor: Connection을 TransactionSynchronizationManager로 관리한다.

* refactor: 와일드카드 제거

* refactor: unbindResource 메서드는 반환값이 존재하지 않는다.

* feat: TSM 테스트코드 작성
  • Loading branch information
wonyongChoi05 authored Oct 12, 2023
1 parent 48d2d9c commit 2cc0bf5
Show file tree
Hide file tree
Showing 13 changed files with 156 additions and 84 deletions.
1 change: 1 addition & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ dependencies {
implementation "org.apache.commons:commons-lang3:3.13.0"
implementation "com.fasterxml.jackson.core:jackson-databind:2.15.2"
implementation "com.h2database:h2:2.2.220"
implementation project(path: ':study')

testImplementation "org.assertj:assertj-core:3.24.2"
testImplementation "org.junit.jupiter:junit-jupiter-api:5.7.2"
Expand Down
7 changes: 0 additions & 7 deletions app/src/main/java/com/techcourse/dao/JdbcUserHistoryDao.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,8 @@
package com.techcourse.dao;

import com.techcourse.domain.UserHistory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;

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

public class JdbcUserHistoryDao implements UserHistoryDao {

private final JdbcTemplate jdbcTemplate;
Expand Down
1 change: 0 additions & 1 deletion app/src/main/java/com/techcourse/domain/UserHistory.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.techcourse.domain;

import java.sql.Connection;
import java.time.LocalDateTime;

public class UserHistory {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import com.techcourse.dao.UserDao;
import com.techcourse.domain.User;

import java.sql.Connection;
import java.util.List;

public class UserRepository {
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.JdbcUserHistoryDao;
import com.techcourse.dao.UserDao;
import com.techcourse.domain.User;
import com.techcourse.domain.UserHistory;
import com.techcourse.repository.UserRepository;

public class AppUserService implements UserService {

private final UserRepository userRepository;
private final JdbcUserHistoryDao jdbcUserHistoryDao;

public AppUserService(final UserDao userDao, final JdbcUserHistoryDao jdbcUserHistoryDao) {
this.userRepository = new UserRepository(userDao);
this.jdbcUserHistoryDao = jdbcUserHistoryDao;
}

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

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

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

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

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

import static com.techcourse.config.DataSourceConfig.getInstance;

public class TxUserService implements UserService {

private final UserService userService;
private final TransactionManager transactionManager;

public TxUserService(UserService userService) {
this.userService = userService;
this.transactionManager = new TransactionManager(getInstance());
}

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

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

@Override
public void changePassword(long id, String newPassword, String createBy) {
transactionManager.execute(connection -> {
userService.changePassword(id, newPassword, createBy);
return null;
});
}

}
40 changes: 5 additions & 35 deletions app/src/main/java/com/techcourse/service/UserService.java
Original file line number Diff line number Diff line change
@@ -1,41 +1,11 @@
package com.techcourse.service;

import com.techcourse.dao.UserDao;
import com.techcourse.dao.JdbcUserHistoryDao;
import com.techcourse.domain.User;
import com.techcourse.domain.UserHistory;
import com.techcourse.repository.UserRepository;
import org.springframework.jdbc.transaction.TransactionManager;

import javax.sql.DataSource;
public interface UserService {

public class UserService {
User findById(final long id);
void insert(final User user);
void changePassword(final long id, final String newPassword, final String createBy);

private final TransactionManager transactionManager;
private final UserRepository userRepository;
private final JdbcUserHistoryDao jdbcUserHistoryDao;

public UserService(final DataSource dataSource, final UserDao userDao, final JdbcUserHistoryDao jdbcUserHistoryDao) {
this.transactionManager = new TransactionManager(dataSource);
this.userRepository = new UserRepository(userDao);
this.jdbcUserHistoryDao = jdbcUserHistoryDao;
}

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

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

public void changePassword(final long id, final String newPassword, final String createBy) {
transactionManager.execute(connection -> {
final var user = findById(id);
user.changePassword(newPassword);
userRepository.update(user);
jdbcUserHistoryDao.log(new UserHistory(user, createBy));
return null;
});
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;

class UserServiceTest {
class AppUserServiceTest {

private JdbcTemplate jdbcTemplate;
private UserDao userDao;
Expand All @@ -32,7 +32,7 @@ void setUp() {
@Test
void testChangePassword() {
final var userHistoryDao = new JdbcUserHistoryDao(jdbcTemplate);
final var userService = new UserService(DataSourceConfig.getInstance(), userDao, userHistoryDao);
final var userService = new AppUserService(userDao, userHistoryDao);

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

final var newPassword = "newPassword";
final var createBy = "gugu";
Expand All @@ -59,4 +62,5 @@ void testTransactionRollback() {

assertThat(actual.getPassword()).isNotEqualTo(newPassword);
}

}
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package org.springframework.jdbc.core;

import org.springframework.jdbc.transaction.TransactionManager;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
Expand All @@ -11,13 +9,14 @@
import java.util.Optional;

import static java.util.Collections.singletonList;
import static org.springframework.jdbc.datasource.DataSourceUtils.getConnection;

public class JdbcTemplate {

private final TransactionManager transactionManager;
private final DataSource dataSource;

public JdbcTemplate(final DataSource dataSource) {
this.transactionManager = new TransactionManager(dataSource);
this.dataSource = dataSource;
}

public int update(final String sql, final Object... conditions) {
Expand All @@ -43,7 +42,7 @@ private <T> T getRowByQuery(final PreparedStatement preparedStatement, final Row
}

private <T> T getResult(final PreparedStatementExecutor<T> executor, final String sql, final Object... conditions) {
Connection connection = transactionManager.getConnection();
Connection connection = getConnection(dataSource);
try (
PreparedStatement preparedStatement = connection.prepareStatement(sql);
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import java.sql.Connection;
import java.sql.SQLException;

// 4단계 미션에서 사용할 것
public abstract class DataSourceUtils {

private DataSourceUtils() {}
Expand All @@ -30,6 +29,7 @@ public static Connection getConnection(DataSource dataSource) throws CannotGetJd
public static void releaseConnection(Connection connection, DataSource dataSource) {
try {
connection.close();
TransactionSynchronizationManager.unbindResource(dataSource);
} catch (SQLException ex) {
throw new CannotGetJdbcConnectionException("Failed to close JDBC Connection");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
import java.sql.Connection;
import java.sql.SQLException;

public class TransactionManager {
import static org.springframework.jdbc.datasource.DataSourceUtils.getConnection;
import static org.springframework.jdbc.datasource.DataSourceUtils.releaseConnection;

private static final ThreadLocal<Connection> connectionInThread = new ThreadLocal<>();
public class TransactionManager {

private final DataSource dataSource;

Expand All @@ -27,54 +28,33 @@ public <T> T execute(final TransactionExecutor<T> transactionExecutor) {
}

public Connection begin() {
Connection connection = getConnection();
Connection connection = getConnection(dataSource);
try {
connection.setAutoCommit(false);
} catch (SQLException e) {
throw new RuntimeException(e);
}
connectionInThread.set(connection);
return connection;
}

public void commit() {
Connection connection = getConnection();
Connection connection = getConnection(dataSource);
try {
connection.commit();
} catch (SQLException e) {
throw new RuntimeException(e);
}
init(connection);
releaseConnection(connection, dataSource);
}

public void rollback() {
Connection connection = getConnection();
Connection connection = getConnection(dataSource);
try {
connection.rollback();
} catch (SQLException e) {
throw new RuntimeException(e);
}
init(connection);
}

private void init(final Connection connection) {
try {
connection.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
connectionInThread.remove();
}

public Connection getConnection() {
if (connectionInThread.get() == null) {
try {
return dataSource.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
return connectionInThread.get();
releaseConnection(connection, dataSource);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import javax.sql.DataSource;
import java.sql.Connection;
import java.util.HashMap;
import java.util.Map;

public abstract class TransactionSynchronizationManager {
Expand All @@ -11,13 +12,25 @@ public abstract class TransactionSynchronizationManager {
private TransactionSynchronizationManager() {}

public static Connection getResource(DataSource key) {
return null;
final Map<DataSource, Connection> resource = resources.get();
if (resource == null) {
return null;
}
return resource.get(key);
}

public static void bindResource(DataSource key, Connection value) {
Map<DataSource, Connection> resource = resources.get();
if (resource == null) {
resource = new HashMap<>();
resources.set(resource);
}
resource.put(key, value);
}

public static Connection unbindResource(DataSource key) {
return null;
public static void unbindResource(DataSource key) {
final Map<DataSource, Connection> resource = resources.get();
resource.remove(key);
}

}
Loading

0 comments on commit 2cc0bf5

Please sign in to comment.