-
Notifications
You must be signed in to change notification settings - Fork 300
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
[4단계 - JDBC 라이브러리 구현하기] 포케(이무송) 미션 제출합니다. #878
Open
fromitive
wants to merge
25
commits into
woowacourse:fromitive
Choose a base branch
from
fromitive:step4
base: fromitive
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
25 commits
Select commit
Hold shift + click to select a range
0b1df04
refactor: 아주 사소한 리팩터링
fromitive b51ab40
feat: transaction 적용
fromitive f284767
feat: transaction 적용할 수 있는 update query 추가
fromitive 342ed40
feat: 비밀번호 변경 시 transaction 적용
fromitive 5517774
test: 의도한 오류 검증구문 추가
fromitive f8a2872
fix: commit 메서드 추가
fromitive 54ae415
refactor: 함수형 인터페이스를 사용하여 try-catch 구문 최소화
fromitive ae5b6cc
refactor: 불필요한 제네릭 제거
fromitive 695fda3
fix: rollback 메서드 추가
fromitive 90cf77c
refactor: 예외를 상세하게 처리
fromitive bf6ac86
refactor: 비즈니스 로직과 트렌젝션 로직 분리
fromitive 67794e6
feat: TransactionSynchronizationManager 구현
fromitive 676a201
feat: connection을 TransactionSynchronizationManager 에서 가져오도록 변경
fromitive cc6741f
Merge remote-tracking branch 'woowacourse/fromitive' into step4
fromitive 6d13c44
refactor: CheckedExceptionExecutor 관련 객체 jdbc로 이동
fromitive e6e2d74
refactor: releaseConnection에서 TransactionSynchronizationManager를 관리하도…
fromitive 5388089
refactor: TransactionSynchronizationManager 의존 제거
fromitive 3e1957e
fix: changePassword 할 때 connection이 close되지 않은 이슈 해결
fromitive 493f3a0
refactor: releaseDataSource 코드 리팩터링
fromitive c6df18a
test: 학습테스트 0 단계
fromitive 82cc622
test: 학습테스트 1 단계
fromitive 8af7a2d
test: 학습테스트 2 단계
fromitive f53e17b
refactor: close()시 TransactionSynchronizationManager에서도 해제 하도록 변경
fromitive 1900e79
refactor: AppUserService에 Transactional 제거
fromitive e85e136
fix: get을 할때 값 존재 여부를 검증
fromitive File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
34 changes: 34 additions & 0 deletions
34
app/src/main/java/com/techcourse/service/AppUserService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
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 UserDao userDao; | ||
private UserHistoryDao userHistoryDao; | ||
|
||
public AppUserService(UserDao userDao, UserHistoryDao userHistoryDao) { | ||
this.userDao = userDao; | ||
this.userHistoryDao = userHistoryDao; | ||
} | ||
|
||
@Override | ||
public User findById(final long id) { | ||
return userDao.findById(id); | ||
} | ||
|
||
@Override | ||
public void insert(final User user) { | ||
userDao.insert(user); | ||
} | ||
|
||
@Override | ||
public void changePassword(final long id, final String newPassword, final String createBy) { | ||
User user = findById(id); | ||
user.changePassword(newPassword); | ||
userDao.update(user); | ||
userHistoryDao.log(new UserHistory(user, createBy)); | ||
} | ||
} |
52 changes: 52 additions & 0 deletions
52
app/src/main/java/com/techcourse/service/TxUserService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package com.techcourse.service; | ||
|
||
import com.interface21.dao.DataAccessException; | ||
import com.interface21.jdbc.datasource.DataSourceUtils; | ||
import com.interface21.jdbc.support.SQLExceptionConsumer; | ||
import com.techcourse.config.DataSourceConfig; | ||
import com.techcourse.domain.User; | ||
import java.sql.Connection; | ||
import java.sql.SQLException; | ||
import javax.sql.DataSource; | ||
|
||
public class TxUserService implements UserService { | ||
|
||
private final UserService userService; | ||
|
||
public TxUserService(UserService userService) { | ||
this.userService = userService; | ||
} | ||
|
||
@Override | ||
public User findById(long id) { | ||
return userService.findById(id); | ||
} | ||
|
||
@Override | ||
public void insert(User user) { | ||
userService.insert(user); | ||
} | ||
|
||
@Override | ||
public void changePassword(final long id, final String newPassword, final String createBy) { | ||
DataSource dataSource = DataSourceConfig.getInstance(); | ||
Connection connection = DataSourceUtils.getConnection(dataSource); | ||
try { | ||
connection.setAutoCommit(false); | ||
userService.changePassword(id, newPassword, createBy); | ||
connection.commit(); | ||
} catch (DataAccessException | SQLException e) { | ||
rollbackTransaction(connection); | ||
throw new DataAccessException(e); | ||
} finally { | ||
DataSourceUtils.releaseDataSource(dataSource); | ||
} | ||
} | ||
|
||
private void rollbackTransaction(Connection connection) { | ||
SQLExceptionConsumer.execute(() -> { | ||
connection.rollback(); | ||
return null; | ||
}, "connection을 rollback하는데 실패했습니다."); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,68 +1,12 @@ | ||
package com.techcourse.service; | ||
|
||
import com.interface21.dao.DataAccessException; | ||
import com.techcourse.dao.UserDao; | ||
import com.techcourse.dao.UserHistoryDao; | ||
import com.techcourse.domain.User; | ||
import com.techcourse.domain.UserHistory; | ||
import com.techcourse.support.SQLExceptionConsumer; | ||
import java.sql.Connection; | ||
import java.sql.SQLException; | ||
import javax.sql.DataSource; | ||
|
||
public class UserService { | ||
public interface UserService { | ||
|
||
private UserDao userDao; | ||
private UserHistoryDao userHistoryDao; | ||
private DataSource dataSource; | ||
User findById(final long id); | ||
|
||
public UserService(DataSource datasource, UserDao userDao, UserHistoryDao userHistoryDao) { | ||
this.dataSource = datasource; | ||
this.userDao = userDao; | ||
this.userHistoryDao = userHistoryDao; | ||
} | ||
void insert(final User user); | ||
|
||
public User findById(final long id) { | ||
return userDao.findById(id); | ||
} | ||
|
||
public void insert(final User user) { | ||
userDao.insert(user); | ||
} | ||
|
||
public void changePassword(final long id, final String newPassword, final String createBy) { | ||
Connection connection = SQLExceptionConsumer.execute(dataSource::getConnection, "connetion을 가져오는데 실패했습니다"); | ||
try { | ||
connection.setAutoCommit(false); | ||
doChangePassword(id, newPassword, createBy, connection); | ||
connection.commit(); | ||
} catch (SQLException e) { | ||
rollbackTransaction(connection); | ||
throw new DataAccessException(e); | ||
} finally { | ||
closeConnection(connection); | ||
} | ||
} | ||
|
||
private void closeConnection(Connection connection) { | ||
SQLExceptionConsumer.execute(() -> { | ||
connection.close(); | ||
return null; | ||
}, "connection을 닫는데 실패했습니다."); | ||
} | ||
|
||
private void rollbackTransaction(Connection connection) { | ||
SQLExceptionConsumer.execute(() -> { | ||
connection.rollback(); | ||
return null; | ||
}, "connection을 rollback하는데 실패했습니다."); | ||
} | ||
|
||
|
||
private void doChangePassword(long id, String newPassword, String createBy, Connection connection) { | ||
User user = findById(id); | ||
user.changePassword(newPassword); | ||
userDao.update(connection, user); | ||
userHistoryDao.log(connection, new UserHistory(user, createBy)); | ||
} | ||
void changePassword(final long id, final String newPassword, final String createBy); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
...rse/support/CheckedExceptionExecutor.java → ...dbc/support/CheckedExceptionExecutor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
...hcourse/support/SQLExceptionConsumer.java → ...21/jdbc/support/SQLExceptionConsumer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
16 changes: 11 additions & 5 deletions
16
.../src/main/java/com/interface21/transaction/support/TransactionSynchronizationManager.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,23 +1,29 @@ | ||
package com.interface21.transaction.support; | ||
|
||
import javax.sql.DataSource; | ||
import java.sql.Connection; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
import javax.sql.DataSource; | ||
|
||
public abstract class TransactionSynchronizationManager { | ||
|
||
private static final ThreadLocal<Map<DataSource, Connection>> resources = new ThreadLocal<>(); | ||
private static final ThreadLocal<Map<DataSource, Connection>> resources = ThreadLocal.withInitial(HashMap::new); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍👍👍 |
||
|
||
private TransactionSynchronizationManager() {} | ||
private TransactionSynchronizationManager() { | ||
} | ||
|
||
public static Connection getResource(DataSource key) { | ||
return null; | ||
Map<DataSource, Connection> binds = resources.get(); | ||
return binds.get(key); | ||
} | ||
|
||
public static void bindResource(DataSource key, Connection value) { | ||
Map<DataSource, Connection> binds = resources.get(); | ||
binds.put(key, value); | ||
} | ||
|
||
public static Connection unbindResource(DataSource key) { | ||
return null; | ||
Map<DataSource, Connection> binds = resources.get(); | ||
return binds.remove(key); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -32,6 +32,7 @@ class JdbcTemplateTest { | |
void setup() throws Exception { | ||
given(this.dataSource.getConnection()).willReturn(this.connection); | ||
given(this.connection.prepareStatement(anyString())).willReturn(this.preparedStatement); | ||
given(this.connection.getAutoCommit()).willReturn(true); | ||
given(this.preparedStatement.executeQuery()).willReturn(this.resultSet); | ||
given(this.preparedStatement.executeQuery(anyString())).willReturn(this.resultSet); | ||
given(this.preparedStatement.getConnection()).willReturn(this.connection); | ||
|
@@ -99,31 +100,6 @@ void updateWithNoParameter() throws SQLException { | |
verifyNoInteractions(resultSet); | ||
} | ||
|
||
@DisplayName("파라미터로 받은 connection을 이용해 update 실행할 때 connection은 close되지 않는다.") | ||
@Test | ||
void updateWithConnectionParameter() throws SQLException { | ||
// given | ||
Connection externalConnection = mock(Connection.class); | ||
PreparedStatement externalPreparedStatement = mock(PreparedStatement.class); | ||
given(externalConnection.prepareStatement(anyString())).willReturn(externalPreparedStatement); | ||
|
||
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); | ||
PreparedStatementSetter preparedStatementSetter = (preparedStatement) -> { | ||
}; | ||
|
||
// when | ||
jdbcTemplate.update("insert into user (account, age, email) values ('pororo', 20, '[email protected]')", | ||
externalConnection, | ||
preparedStatementSetter); | ||
|
||
// then | ||
verify(externalPreparedStatement, times(0)).setObject(anyInt(), any()); | ||
verify(externalPreparedStatement).close(); | ||
verify(externalConnection, times(0)).close(); | ||
verifyNoInteractions(resultSet); | ||
} | ||
|
||
|
||
@DisplayName("query 내에 쿼리문 실행 중 예외가 발생할 경우 관련된 리소스들이 닫혀야 한다.") | ||
@Test | ||
void queryWithExecuteQueryException() throws SQLException { | ||
|
@@ -332,6 +308,30 @@ void queryForObjectWithNoResultException() throws SQLException { | |
verify(this.preparedStatement).close(); | ||
} | ||
|
||
@DisplayName("connection.setAutoCommit이 false일 경우 close되지 않는다.") | ||
@Test | ||
void notClosedWhenSetAutoCommitIsFalse() throws SQLException { | ||
// given | ||
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); | ||
given(connection.getAutoCommit()).willReturn(false); | ||
PreparedStatementSetter preparedStatementSetter = (preparedStatement) -> { | ||
preparedStatement.setString(1, "pororo"); | ||
preparedStatement.setString(2, "poke"); | ||
}; | ||
SQLException sqlException = new SQLException("업데이트 중 예외 발생"); | ||
given(this.preparedStatement.executeUpdate()).willThrow(sqlException); | ||
|
||
// when | ||
assertThatExceptionOfType(DataAccessException.class) | ||
.isThrownBy(() -> jdbcTemplate.update("update error", preparedStatementSetter)) | ||
.withCause(sqlException); | ||
|
||
// then | ||
verify(preparedStatement).close(); | ||
verify(connection, times(0)).close(); | ||
verifyNoInteractions(resultSet); | ||
} | ||
|
||
record TestUser(String account, String password) { | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
분리된 이유를 설명해주실 수 있나요??ㅎㅎ
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
jdbctemplate에서 execute메서드를 실행할 때 트렌젝션의 유무의 따라 커넥션을 닫는 여부를 결정해야 하는데,
트렌젝션이 설정되어 있으면 롤백을 위해 커넥션을 닫으면 안되서 분리하게 되었습니다..!