Skip to content

Commit c2a887b

Browse files
step3 구현 (#1210)
1 parent cc5bd86 commit c2a887b

File tree

6 files changed

+230
-53
lines changed

6 files changed

+230
-53
lines changed

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

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import org.slf4j.Logger;
1111
import org.slf4j.LoggerFactory;
1212

13+
import java.sql.Connection;
1314
import java.sql.SQLSyntaxErrorException;
1415
import java.util.List;
1516

@@ -29,6 +30,79 @@ public UserDao(final JdbcTemplate jdbcTemplate) {
2930
this.jdbcTemplate = jdbcTemplate;
3031
}
3132

33+
public Connection getConnection() {
34+
return jdbcTemplate.getConnection();
35+
}
36+
37+
public void startTransaction(Connection connection) {
38+
jdbcTemplate.startTransaction(connection);
39+
}
40+
41+
public void commitTransaction(Connection connection) {
42+
jdbcTemplate.commitTransaction(connection);
43+
}
44+
45+
public void insertWithTransaction(final User user, final Connection connection) {
46+
CommandSpecification specification = new CommandSpecification(createPreparedStatementSpecification(
47+
"insert into users (account, password, email) values (?, ?, ?)",
48+
List.of(
49+
new PreparedStatementParameter(1, user.getAccount()),
50+
new PreparedStatementParameter(2, user.getPassword()),
51+
new PreparedStatementParameter(3, user.getEmail())
52+
)
53+
));
54+
jdbcTemplate.insertWithTransaction(specification, connection);
55+
}
56+
57+
public void updateWithTransaction(final User user, final Connection connection) {
58+
CommandSpecification specification = new CommandSpecification(createPreparedStatementSpecification(
59+
"update users set account = ?, password = ?, email = ? where id = ?",
60+
List.of(
61+
new PreparedStatementParameter(1, user.getAccount()),
62+
new PreparedStatementParameter(2, user.getPassword()),
63+
new PreparedStatementParameter(3, user.getEmail()),
64+
new PreparedStatementParameter(4, user.getId())
65+
)
66+
));
67+
jdbcTemplate.updateWithTransaction(specification, connection);
68+
}
69+
70+
public List<User> findAllWithTransaction(final Connection connection) {
71+
QuerySpecification<User> specification = new QuerySpecification<>(
72+
USER_ROW_MAPPER,
73+
createPreparedStatementSpecification(
74+
"select id, account, password, email from users",
75+
List.of()
76+
)
77+
);
78+
return jdbcTemplate.findAllWithTransaction(specification, connection);
79+
}
80+
81+
public User findByIdWithTransaction(final Long id, final Connection connection) {
82+
QuerySpecification<User> specification = new QuerySpecification<>(
83+
USER_ROW_MAPPER,
84+
createPreparedStatementSpecification(
85+
"select id, account, password, email from users where id = ?",
86+
List.of(new PreparedStatementParameter(1, id))
87+
)
88+
);
89+
return jdbcTemplate.findOneWithTransaction(specification, connection)
90+
.orElseThrow(() -> new IllegalArgumentException("존재하지 않는 유저입니다."));
91+
}
92+
93+
public User findByAccountWithTransaction(final String account, final Connection connection) {
94+
95+
QuerySpecification<User> specification = new QuerySpecification<>(
96+
USER_ROW_MAPPER,
97+
createPreparedStatementSpecification(
98+
"select id, account, password, email from users where account = ?",
99+
List.of(new PreparedStatementParameter(1, account))
100+
)
101+
);
102+
return jdbcTemplate.findOneWithTransaction(specification, connection)
103+
.orElseThrow(() -> new IllegalArgumentException("존재하지 않는 유저입니다."));
104+
}
105+
32106
public void insert(final User user) {
33107
CommandSpecification specification = new CommandSpecification(createPreparedStatementSpecification(
34108
"insert into users (account, password, email) values (?, ?, ?)",
Lines changed: 50 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,72 @@
11
package com.techcourse.dao;
22

3-
import com.techcourse.domain.UserHistory;
43
import com.interface21.jdbc.core.JdbcTemplate;
4+
import com.interface21.jdbc.core.execution.command.CommandSpecification;
5+
import com.interface21.jdbc.core.preparedstatement.PreparedStatementParameter;
6+
import com.interface21.jdbc.core.preparedstatement.PreparedStatementSpecification;
7+
import com.techcourse.domain.UserHistory;
58
import org.slf4j.Logger;
69
import org.slf4j.LoggerFactory;
710

8-
import javax.sql.DataSource;
911
import java.sql.Connection;
10-
import java.sql.PreparedStatement;
11-
import java.sql.SQLException;
12+
import java.sql.SQLSyntaxErrorException;
13+
import java.util.List;
1214

1315
public class UserHistoryDao {
1416

1517
private static final Logger log = LoggerFactory.getLogger(UserHistoryDao.class);
1618

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

2321
public UserHistoryDao(final JdbcTemplate jdbcTemplate) {
24-
this.dataSource = null;
22+
this.jdbcTemplate = jdbcTemplate;
2523
}
2624

2725
public void log(final UserHistory userHistory) {
28-
final var sql = "insert into user_history (user_id, account, password, email, created_at, created_by) values (?, ?, ?, ?, ?, ?)";
26+
CommandSpecification commandSpecification = new CommandSpecification(
27+
createPreparedStatementSpecification(
28+
"insert into user_history (user_id, account, password, email, created_at, created_by) values (?, ?, ?, ?, ?, ?)",
29+
List.of(
30+
new PreparedStatementParameter(1, userHistory.getUserId()),
31+
new PreparedStatementParameter(2, userHistory.getAccount()),
32+
new PreparedStatementParameter(3, userHistory.getPassword()),
33+
new PreparedStatementParameter(4, userHistory.getEmail()),
34+
new PreparedStatementParameter(5, userHistory.getCreatedAt()),
35+
new PreparedStatementParameter(6, userHistory.getCreateBy())
36+
)
37+
)
38+
);
39+
jdbcTemplate.insert(commandSpecification);
40+
}
41+
42+
public void logWithTransaction(final UserHistory userHistory, final Connection connection) {
43+
CommandSpecification commandSpecification = new CommandSpecification(
44+
createPreparedStatementSpecification(
45+
"insert into user_history (user_id, account, password, email, created_at, created_by) values (?, ?, ?, ?, ?, ?)",
46+
List.of(
47+
new PreparedStatementParameter(1, userHistory.getUserId()),
48+
new PreparedStatementParameter(2, userHistory.getAccount()),
49+
new PreparedStatementParameter(3, userHistory.getPassword()),
50+
new PreparedStatementParameter(4, userHistory.getEmail()),
51+
new PreparedStatementParameter(5, userHistory.getCreatedAt()),
52+
new PreparedStatementParameter(6, userHistory.getCreateBy())
53+
)
54+
)
55+
);
56+
jdbcTemplate.insertWithTransaction(commandSpecification, connection);
57+
}
2958

30-
Connection conn = null;
31-
PreparedStatement pstmt = null;
59+
private PreparedStatementSpecification createPreparedStatementSpecification(
60+
String sql,
61+
List<PreparedStatementParameter> parameters
62+
) {
3263
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) {}
54-
55-
try {
56-
if (conn != null) {
57-
conn.close();
58-
}
59-
} catch (SQLException ignored) {}
64+
return PreparedStatementSpecification
65+
.builder(sql)
66+
.parameters(parameters)
67+
.build();
68+
} catch (SQLSyntaxErrorException e) {
69+
throw new IllegalArgumentException(e);
6070
}
6171
}
6272
}

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

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
import com.techcourse.domain.User;
66
import com.techcourse.domain.UserHistory;
77

8+
import java.sql.Connection;
9+
import java.sql.SQLException;
10+
811
public class UserService {
912

1013
private final UserDao userDao;
@@ -23,10 +26,18 @@ public void insert(final User user) {
2326
userDao.insert(user);
2427
}
2528

26-
public void changePassword(final long id, final String newPassword, final String createBy) {
29+
public void changePassword(final long id, final String newPassword, final String createBy) throws SQLException {
2730
final var user = findById(id);
2831
user.changePassword(newPassword);
29-
userDao.update(user);
30-
userHistoryDao.log(new UserHistory(user, createBy));
32+
Connection connection = userDao.getConnection();
33+
try {
34+
userDao.startTransaction(connection);
35+
userDao.updateWithTransaction(user, connection);
36+
userHistoryDao.logWithTransaction(new UserHistory(user, createBy), connection);
37+
userDao.commitTransaction(connection);
38+
} catch (Exception e) {
39+
connection.rollback();
40+
throw e;
41+
}
3142
}
3243
}
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
package com.techcourse.service;
22

3-
import com.techcourse.dao.UserHistoryDao;
4-
import com.techcourse.domain.UserHistory;
53
import com.interface21.dao.DataAccessException;
64
import com.interface21.jdbc.core.JdbcTemplate;
5+
import com.techcourse.dao.UserHistoryDao;
6+
import com.techcourse.domain.UserHistory;
77

88
public class MockUserHistoryDao extends UserHistoryDao {
99

@@ -12,7 +12,7 @@ public MockUserHistoryDao(final JdbcTemplate jdbcTemplate) {
1212
}
1313

1414
@Override
15-
public void log(final UserHistory userHistory) {
15+
public void logWithTransaction(final UserHistory userHistory, final java.sql.Connection connection) {
1616
throw new DataAccessException();
1717
}
1818
}

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

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

3+
import com.interface21.dao.DataAccessException;
4+
import com.interface21.jdbc.core.JdbcTemplate;
35
import com.techcourse.config.DataSourceConfig;
46
import com.techcourse.dao.UserDao;
57
import com.techcourse.dao.UserHistoryDao;
68
import com.techcourse.domain.User;
79
import com.techcourse.support.jdbc.init.DatabasePopulatorUtils;
8-
import com.interface21.dao.DataAccessException;
9-
import com.interface21.jdbc.core.JdbcTemplate;
1010
import org.junit.jupiter.api.BeforeEach;
11-
import org.junit.jupiter.api.Disabled;
1211
import org.junit.jupiter.api.Test;
1312

13+
import java.sql.SQLException;
14+
1415
import static org.assertj.core.api.Assertions.assertThat;
1516
import static org.junit.jupiter.api.Assertions.assertThrows;
1617

17-
@Disabled
1818
class UserServiceTest {
1919

2020
private JdbcTemplate jdbcTemplate;
@@ -31,7 +31,7 @@ void setUp() {
3131
}
3232

3333
@Test
34-
void testChangePassword() {
34+
void testChangePassword() throws SQLException {
3535
final var userHistoryDao = new UserHistoryDao(jdbcTemplate);
3636
final var userService = new UserService(userDao, userHistoryDao);
3737

@@ -53,8 +53,10 @@ void testTransactionRollback() {
5353
final var newPassword = "newPassword";
5454
final var createBy = "gugu";
5555
// 트랜잭션이 정상 동작하는지 확인하기 위해 의도적으로 MockUserHistoryDao에서 예외를 발생시킨다.
56-
assertThrows(DataAccessException.class,
57-
() -> userService.changePassword(1L, newPassword, createBy));
56+
assertThrows(
57+
DataAccessException.class,
58+
() -> userService.changePassword(1L, newPassword, createBy)
59+
);
5860

5961
final var actual = userService.findById(1L);
6062

0 commit comments

Comments
 (0)