Skip to content

Commit 7c2c119

Browse files
authored
[4단계 - Transaction synchronization 적용하기] 미미(홍향미) 미션 제출합니다. (#1196)
* feat: DataSourceUtils 사용 * feat: UserService 추상화 * style: EOF 설정
1 parent 1eae452 commit 7c2c119

File tree

8 files changed

+189
-282
lines changed

8 files changed

+189
-282
lines changed
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package com.techcourse.service;
2+
3+
import com.techcourse.dao.UserDao;
4+
import com.techcourse.dao.UserHistoryDao;
5+
import com.techcourse.domain.User;
6+
import com.techcourse.domain.UserHistory;
7+
8+
public class AppUserService implements UserService {
9+
10+
private final UserDao userDao;
11+
private final UserHistoryDao userHistoryDao;
12+
13+
public AppUserService(final UserDao userDao, final UserHistoryDao userHistoryDao) {
14+
this.userDao = userDao;
15+
this.userHistoryDao = userHistoryDao;
16+
}
17+
18+
@Override
19+
public User findById(final long id) {
20+
return userDao.findById(id)
21+
.orElseThrow(() -> new IllegalArgumentException("User not found"));
22+
}
23+
24+
@Override
25+
public void save(final User user) {
26+
userDao.insert(user);
27+
}
28+
29+
@Override
30+
public void changePassword(final long id, final String newPassword, final String createdBy) {
31+
final var user = findById(id);
32+
user.changePassword(newPassword);
33+
userDao.update(user);
34+
35+
userHistoryDao.log(new UserHistory(user, createdBy));
36+
}
37+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package com.techcourse.service;
2+
3+
import com.interface21.dao.DataAccessException;
4+
import com.interface21.transaction.DataSourceTransactionManager;
5+
import com.techcourse.config.DataSourceConfig;
6+
import com.techcourse.domain.User;
7+
8+
public class TxUserService implements UserService {
9+
10+
private final UserService userService;
11+
private final DataSourceTransactionManager transactionManager;
12+
13+
public TxUserService(final UserService userService) {
14+
this.userService = userService;
15+
this.transactionManager = new DataSourceTransactionManager(DataSourceConfig.getInstance());
16+
}
17+
18+
@Override
19+
public User findById(final long id) {
20+
return userService.findById(id);
21+
}
22+
23+
@Override
24+
public void save(final User user) {
25+
userService.save(user);
26+
}
27+
28+
@Override
29+
public void changePassword(final long id, final String newPassword, final String createdBy) {
30+
transactionManager.bindConnection();
31+
try {
32+
userService.changePassword(id, newPassword, createdBy);
33+
transactionManager.commit();
34+
} catch (final Exception e) {
35+
transactionManager.rollback();
36+
throw new DataAccessException(e);
37+
}
38+
}
39+
}
Lines changed: 4 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,10 @@
11
package com.techcourse.service;
22

3-
4-
import com.interface21.dao.DataAccessException;
5-
import com.interface21.transaction.DataSourceTransactionManager;
6-
import com.techcourse.dao.UserDao;
7-
import com.techcourse.dao.UserHistoryDao;
83
import com.techcourse.domain.User;
9-
import com.techcourse.domain.UserHistory;
10-
11-
public class UserService {
12-
13-
private final UserDao userDao;
14-
private final UserHistoryDao userHistoryDao;
15-
private final DataSourceTransactionManager transactionManager;
16-
17-
public UserService(final UserDao userDao,
18-
final UserHistoryDao userHistoryDao,
19-
final DataSourceTransactionManager transactionManager
20-
) {
21-
this.userDao = userDao;
22-
this.userHistoryDao = userHistoryDao;
23-
this.transactionManager = transactionManager;
24-
}
25-
26-
public User findById(final long id) {
27-
return userDao.findById(id)
28-
.orElseThrow(() -> new IllegalArgumentException("User not found"));
29-
}
30-
31-
public void insert(final User user) {
32-
userDao.insert(user);
33-
}
34-
35-
public void changePassword(final long id, final String newPassword, final String createBy) {
36-
transactionManager.bindConnection();
37-
try {
38-
final var user = findById(id);
39-
user.changePassword(newPassword);
40-
userDao.update(user);
414

42-
userHistoryDao.log(new UserHistory(user, createBy));
5+
public interface UserService {
436

44-
transactionManager.commit();
45-
} catch (final Exception e) {
46-
transactionManager.rollback();
47-
throw new DataAccessException(e);
48-
}
49-
}
7+
User findById(final long id);
8+
void save(final User user);
9+
void changePassword(final long id, final String newPassword, final String createdBy);
5010
}

app/src/test/java/com/techcourse/service/UserServiceTest.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.techcourse.service;
22

3-
import com.interface21.transaction.DataSourceTransactionManager;
43
import com.techcourse.config.DataSourceConfig;
54
import com.techcourse.dao.UserDao;
65
import com.techcourse.dao.UserHistoryDao;
@@ -18,13 +17,11 @@ class UserServiceTest {
1817

1918
private JdbcTemplate jdbcTemplate;
2019
private UserDao userDao;
21-
private DataSourceTransactionManager transactionManager;
2220

2321
@BeforeEach
2422
void setUp() {
2523
this.jdbcTemplate = new JdbcTemplate(DataSourceConfig.getInstance());
2624
this.userDao = new UserDao(jdbcTemplate);
27-
this.transactionManager = new DataSourceTransactionManager(DataSourceConfig.getInstance());
2825

2926
DatabasePopulatorUtils.execute(DataSourceConfig.getInstance());
3027
final var user = new User("gugu", "password", "[email protected]");
@@ -34,7 +31,8 @@ void setUp() {
3431
@Test
3532
void testChangePassword() {
3633
final var userHistoryDao = new UserHistoryDao(jdbcTemplate);
37-
final var userService = new UserService(userDao, userHistoryDao, transactionManager);
34+
final var appUserService = new AppUserService(userDao, userHistoryDao);
35+
final var userService = new TxUserService(appUserService);
3836

3937
final var newPassword = "qqqqq";
4038
final var createBy = "gugu";
@@ -49,13 +47,16 @@ void testChangePassword() {
4947
void testTransactionRollback() {
5048
// 트랜잭션 롤백 테스트를 위해 mock으로 교체
5149
final var userHistoryDao = new MockUserHistoryDao(jdbcTemplate);
52-
final var userService = new UserService(userDao, userHistoryDao, transactionManager);
50+
// 애플리케이션 서비스
51+
final var appUserService = new AppUserService(userDao, userHistoryDao);
52+
// 트랜잭션 서비스 추상화
53+
final var userService = new TxUserService(appUserService);
5354

5455
final var newPassword = "newPassword";
55-
final var createBy = "gugu";
56+
final var createdBy = "gugu";
5657
// 트랜잭션이 정상 동작하는지 확인하기 위해 의도적으로 MockUserHistoryDao에서 예외를 발생시킨다.
5758
assertThrows(DataAccessException.class,
58-
() -> userService.changePassword(1L, newPassword, createBy));
59+
() -> userService.changePassword(1L, newPassword, createdBy));
5960

6061
final var actual = userService.findById(1L);
6162

jdbc/src/main/java/com/interface21/jdbc/datasource/DataSourceUtils.java

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,36 +2,42 @@
22

33
import com.interface21.jdbc.CannotGetJdbcConnectionException;
44
import com.interface21.transaction.support.TransactionSynchronizationManager;
5+
import org.slf4j.Logger;
6+
import org.slf4j.LoggerFactory;
57

68
import javax.sql.DataSource;
79
import java.sql.Connection;
810
import java.sql.SQLException;
911

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

13-
private DataSourceUtils() {}
14+
private static final Logger log = LoggerFactory.getLogger(DataSourceUtils.class);
1415

15-
public static Connection getConnection(DataSource dataSource) throws CannotGetJdbcConnectionException {
16-
Connection connection = TransactionSynchronizationManager.getResource(dataSource);
16+
private DataSourceUtils() {
17+
}
18+
19+
public static Connection getConnection(final DataSource dataSource) {
20+
final var connection = TransactionSynchronizationManager.getResource(dataSource);
1721
if (connection != null) {
1822
return connection;
1923
}
20-
2124
try {
22-
connection = dataSource.getConnection();
23-
TransactionSynchronizationManager.bindResource(dataSource, connection);
24-
return connection;
25-
} catch (SQLException ex) {
26-
throw new CannotGetJdbcConnectionException("Failed to obtain JDBC Connection", ex);
25+
return dataSource.getConnection();
26+
} catch (final SQLException e) {
27+
throw new CannotGetJdbcConnectionException("Failed to obtain JDBC Connection", e);
2728
}
2829
}
2930

30-
public static void releaseConnection(Connection connection, DataSource dataSource) {
31-
try {
32-
connection.close();
33-
} catch (SQLException ex) {
34-
throw new CannotGetJdbcConnectionException("Failed to close JDBC Connection");
31+
public static void releaseConnection(final Connection connection, final DataSource dataSource) {
32+
if (TransactionSynchronizationManager.hasResource(dataSource)) {
33+
return;
34+
}
35+
if (connection != null) {
36+
try {
37+
connection.close();
38+
} catch (final SQLException e) {
39+
log.debug("Could not close JDBC Connection", e);
40+
}
3541
}
3642
}
3743
}

0 commit comments

Comments
 (0)