Skip to content

Commit cde2601

Browse files
authored
JDBC Step3 띠용 (#1213)
* refactor: JdbcTemplate과 UserHistoryDao 변경 및 코드 개선 - JdbcTemplate에 getDataSource 메서드 추가 - UserHistoryDao 생성자에서 JdbcTemplate의 getDataSource 활용 - try-with-resources 문법으로 리소스 관리 개선 - 불필요한 finally 블록 제거 및 코드 간결화 - UserServiceTest의 @disabled 제거 - UserService에 비밀번호 변경 트랜잭션 적용 로직 주석 추가 * refactor: UserDao 및 UserService에서 트랜잭션 처리 로직 추가 및 JdbcTemplate 개선 - UserDao에 Connection을 사용하는 update 메서드 추가 - UserService에서 비밀번호 변경 시 트랜잭션 처리 로직 추가 - JdbcTemplate에 Connection을 지원하는 update 메서드 구현 - UserHistoryDao에 Connection 기반 로그 작성 메서드 추가 - 안전한 롤백 메서드(safeRollback) 구현 - 예외 처리 방식 개선 및 코드 가독성 향상 * refactor: UserHistoryDao의 JdbcTemplate 활용으로 코드 간결화 - PreparedStatement 및 Connection 관련 코드 제거 - JdbcTemplate의 update 메서드 사용으로 중복 제거 - 리소스 관리 개선 및 가독성 향상 * refactor: UserService에 safeRollback 로깅 추가 - safeRollback 메서드에서 Connection null 체크 로직 추가 - Connection이 null인 경우 디버그 로그 출력 * refactor: UserService에서 예외 타입 변경으로 예외 처리 통일성 개선 - RuntimeException 대신 DataAccessException으로 변경 - 예외 타입 명확화로 코드 가독성 향상 * refactor: UserService 및 UserHistoryDao 리팩토링으로 가독성 및 일관성 개선 - UserDao에 getConnection 메서드 추가로 중복 제거 - UserService에서 UserDao의 getConnection 활용 및 트랜잭션 코드 단축 - UserHistoryDao의 SQL 상수화로 코드 재 * feat: TransactionManager 도입으로 트랜잭션 관리 리팩토링 - TransactionManager 및 TransactionalAction 인터페이스 추가 - UserService에 TransactionManager 적용 - 트랜잭션 로직 캡슐화로 코드 중복 제거 및 안정성 강화 * refactor: 불필요한 import 제거 및 코드 스타일 수정 - 사용되지 않는 Reflections 관련 import 제거 - 예외 메시지 문자열 formatter 통일 - 코드 명료성과 가독성 향상 * refactor: 예외 메시지 정리로 코드 가독성 및 명확성 개선 - DataAccessException 및 RuntimeException의 예외 메시지 형식 수정 - 메시지에 Exception 객체를 포함하여 디버깅 정보 강화 * refactor: 트랜잭션 및 DataSource 초기화 로직 개선 - TransactionManager에 autoCommit 설정 추가로 롤백 후 안정성 강화 - UserService에서 DataSourceConfig를 활용한 DataSource 초기화로 의존성 관리 개선
1 parent 4d604c1 commit cde2601

File tree

8 files changed

+119
-47
lines changed

8 files changed

+119
-47
lines changed

app/src/main/java/com/techcourse/dao/UserDao.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package com.techcourse.dao;
22

3+
import java.sql.Connection;
34
import com.techcourse.domain.User;
45
import com.interface21.jdbc.core.JdbcTemplate;
6+
import java.sql.SQLException;
7+
import javax.sql.DataSource;
58
import org.slf4j.Logger;
69
import org.slf4j.LoggerFactory;
710

@@ -27,6 +30,11 @@ public void update(final User user) {
2730
jdbcTemplate.update(sql, user.getAccount(), user.getPassword(), user.getEmail(), user.getId());
2831
}
2932

33+
public void update(Connection connection, final User user) {
34+
final var sql = "update users set account = ?, password = ?, email = ? where id = ?";
35+
jdbcTemplate.update(connection, sql, user.getAccount(), user.getPassword(), user.getEmail(), user.getId());
36+
}
37+
3038
public List<User> findAll() {
3139
final var sql = "select id, account, password, email from users";
3240
return jdbcTemplate.query(sql, new UserRowMapper());
@@ -41,4 +49,8 @@ public User findByAccount(final String account) {
4149
final var sql = "select id, account, password, email from users where account = ?";
4250
return jdbcTemplate.executeQueryForObject(sql, new UserRowMapper(), account);
4351
}
52+
53+
public DataSource getDataSource() {
54+
return jdbcTemplate.getDataSource();
55+
}
4456
}
Lines changed: 24 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,42 @@
11
package com.techcourse.dao;
22

3-
import com.techcourse.domain.UserHistory;
43
import com.interface21.jdbc.core.JdbcTemplate;
4+
import com.techcourse.domain.UserHistory;
5+
import java.sql.Connection;
56
import org.slf4j.Logger;
67
import org.slf4j.LoggerFactory;
78

8-
import javax.sql.DataSource;
9-
import java.sql.Connection;
10-
import java.sql.PreparedStatement;
11-
import java.sql.SQLException;
12-
139
public class UserHistoryDao {
1410

1511
private static final Logger log = LoggerFactory.getLogger(UserHistoryDao.class);
12+
public static final String INSERT_USER_HISTORY_SQL = "insert into user_history (user_id, account, password, email, created_at, created_by) values (?, ?, ?, ?, ?, ?)";
1613

17-
private final DataSource dataSource;
18-
19-
public UserHistoryDao(final DataSource dataSource) {
20-
this.dataSource = dataSource;
21-
}
14+
private final JdbcTemplate jdbcTemplate;
2215

2316
public UserHistoryDao(final JdbcTemplate jdbcTemplate) {
24-
this.dataSource = null;
17+
this.jdbcTemplate = jdbcTemplate;
2518
}
2619

2720
public void log(final UserHistory userHistory) {
28-
final var sql = "insert into user_history (user_id, account, password, email, created_at, created_by) values (?, ?, ?, ?, ?, ?)";
29-
30-
Connection conn = null;
31-
PreparedStatement pstmt = null;
32-
try {
33-
conn = dataSource.getConnection();
34-
pstmt = conn.prepareStatement(sql);
35-
36-
log.debug("query : {}", sql);
37-
38-
pstmt.setLong(1, userHistory.getUserId());
39-
pstmt.setString(2, userHistory.getAccount());
40-
pstmt.setString(3, userHistory.getPassword());
41-
pstmt.setString(4, userHistory.getEmail());
42-
pstmt.setObject(5, userHistory.getCreatedAt());
43-
pstmt.setString(6, userHistory.getCreateBy());
44-
pstmt.executeUpdate();
45-
} catch (SQLException e) {
46-
log.error(e.getMessage(), e);
47-
throw new RuntimeException(e);
48-
} finally {
49-
try {
50-
if (pstmt != null) {
51-
pstmt.close();
52-
}
53-
} catch (SQLException ignored) {}
21+
jdbcTemplate.update(INSERT_USER_HISTORY_SQL,
22+
userHistory.getUserId(),
23+
userHistory.getAccount(),
24+
userHistory.getPassword(),
25+
userHistory.getEmail(),
26+
userHistory.getCreatedAt(),
27+
userHistory.getCreateBy()
28+
);
29+
}
5430

55-
try {
56-
if (conn != null) {
57-
conn.close();
58-
}
59-
} catch (SQLException ignored) {}
60-
}
31+
public void log(final Connection conn, final UserHistory userHistory) {
32+
jdbcTemplate.update(conn,
33+
INSERT_USER_HISTORY_SQL,
34+
userHistory.getUserId(),
35+
userHistory.getAccount(),
36+
userHistory.getPassword(),
37+
userHistory.getEmail(),
38+
userHistory.getCreatedAt(),
39+
userHistory.getCreateBy()
40+
);
6141
}
6242
}

app/src/main/java/com/techcourse/service/UserService.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,31 @@
11
package com.techcourse.service;
22

3+
import com.interface21.dao.DataAccessException;
4+
import com.interface21.jdbc.JdbcExecutionException;
5+
import com.interface21.transaction.TransactionManager;
6+
import com.techcourse.config.DataSourceConfig;
37
import com.techcourse.dao.UserDao;
48
import com.techcourse.dao.UserHistoryDao;
59
import com.techcourse.domain.User;
610
import com.techcourse.domain.UserHistory;
11+
import java.sql.Connection;
12+
import java.sql.SQLException;
13+
import javax.sql.DataSource;
14+
import org.slf4j.Logger;
15+
import org.slf4j.LoggerFactory;
716

817
public class UserService {
918

19+
private static final Logger log = LoggerFactory.getLogger(UserService.class);
1020
private final UserDao userDao;
1121
private final UserHistoryDao userHistoryDao;
22+
private final TransactionManager transactionManager;
1223

1324
public UserService(final UserDao userDao, final UserHistoryDao userHistoryDao) {
1425
this.userDao = userDao;
1526
this.userHistoryDao = userHistoryDao;
27+
DataSource dataSource = DataSourceConfig.getInstance();
28+
transactionManager = new TransactionManager(dataSource);
1629
}
1730

1831
public User findById(final long id) {
@@ -26,7 +39,9 @@ public void insert(final User user) {
2639
public void changePassword(final long id, final String newPassword, final String createBy) {
2740
final var user = findById(id);
2841
user.changePassword(newPassword);
29-
userDao.update(user);
30-
userHistoryDao.log(new UserHistory(user, createBy));
42+
transactionManager.executeTransaction(connection -> {
43+
userDao.update(connection, user);
44+
userHistoryDao.log(connection, new UserHistory(user, createBy));
45+
});
3146
}
3247
}

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.techcourse.domain.UserHistory;
55
import com.interface21.dao.DataAccessException;
66
import com.interface21.jdbc.core.JdbcTemplate;
7+
import java.sql.Connection;
78

89
public class MockUserHistoryDao extends UserHistoryDao {
910

@@ -15,4 +16,9 @@ public MockUserHistoryDao(final JdbcTemplate jdbcTemplate) {
1516
public void log(final UserHistory userHistory) {
1617
throw new DataAccessException();
1718
}
19+
20+
@Override
21+
public void log(final Connection connection, final UserHistory userHistory) {
22+
throw new DataAccessException();
23+
}
1824
}

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
import static org.assertj.core.api.Assertions.assertThat;
1515
import static org.junit.jupiter.api.Assertions.assertThrows;
1616

17-
@Disabled
1817
class UserServiceTest {
1918

2019
private JdbcTemplate jdbcTemplate;

jdbc/src/main/java/com/interface21/jdbc/core/JdbcTemplate.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,21 @@ private <T> T execute(String sql, PreparedStatementExecutor<T> executor, Object[
3838
}
3939
}
4040

41+
public int update(final Connection connection, final String sql, final Object... parameters) {
42+
return execute(connection, sql, PreparedStatement::executeUpdate, parameters);
43+
}
44+
45+
private <T> T execute(Connection conn, String sql, PreparedStatementExecutor<T> executor, Object[] parameters) {
46+
try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
47+
setStatementParameters(pstmt, parameters);
48+
log.debug("query : {}, params : {}", sql, Arrays.toString(parameters));
49+
return executor.execute(pstmt);
50+
} catch (SQLException e) {
51+
log.error("executeUpdate failed. sql={}, params={}", sql, Arrays.toString(parameters), e);
52+
throw new JdbcExecutionException("쿼리 실행 실패 : " + e.getMessage());
53+
}
54+
}
55+
4156
private void setStatementParameters(PreparedStatement pstmt, Object... parameters) throws SQLException {
4257
for (int i = 0; i < parameters.length; i++) {
4358
pstmt.setObject(i + 1, parameters[i]);
@@ -66,4 +81,8 @@ public <T> T executeQueryForObject(final String sql, final RowMapper<T> rowMappe
6681
}
6782
return results.getFirst();
6883
}
84+
85+
public DataSource getDataSource() {
86+
return this.dataSource;
87+
}
6988
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.interface21.transaction;
2+
3+
import com.interface21.dao.DataAccessException;
4+
import java.sql.Connection;
5+
import java.sql.SQLException;
6+
import javax.sql.DataSource;
7+
8+
public class TransactionManager {
9+
10+
private final DataSource dataSource;
11+
12+
public TransactionManager(DataSource dataSource) {
13+
this.dataSource = dataSource;
14+
}
15+
16+
public void executeTransaction(final TransactionalAction action) {
17+
try (Connection connection = dataSource.getConnection()) {
18+
// transaction start
19+
connection.setAutoCommit(false);
20+
try {
21+
action.execute(connection);
22+
connection.commit();
23+
} catch (Exception e) {
24+
connection.rollback();
25+
throw new DataAccessException("트랜잭션 오류발생으로 롤백", e);
26+
}
27+
connection.setAutoCommit(true);
28+
} catch (SQLException e) {
29+
throw new RuntimeException("커넥션 오류 발생", e);
30+
}
31+
}
32+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.interface21.transaction;
2+
3+
import java.sql.Connection;
4+
5+
@FunctionalInterface
6+
public interface TransactionalAction {
7+
8+
void execute(Connection connection);
9+
}

0 commit comments

Comments
 (0)