-
Notifications
You must be signed in to change notification settings - Fork 220
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
[JDBC 라이브러리 구현하기 - 4단계] 다즐(최우창) 미션 제출합니다. #566
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
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 final UserDao userDao; | ||
private final UserHistoryDao userHistoryDao; | ||
|
||
public AppUserService(UserDao userDao, UserHistoryDao userHistoryDao) { | ||
this.userDao = userDao; | ||
this.userHistoryDao = userHistoryDao; | ||
} | ||
|
||
@Override | ||
public User findById(long id) { | ||
return userDao.findById(id); | ||
} | ||
|
||
@Override | ||
public void insert(User user) { | ||
userDao.insert(user); | ||
} | ||
|
||
@Override | ||
public void changePassword(long id, String newPassword, String createBy) { | ||
var user = findById(id); | ||
user.changePassword(newPassword); | ||
userDao.update(user); | ||
userHistoryDao.log(new UserHistory(user, createBy)); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package com.techcourse.service; | ||
|
||
import com.techcourse.domain.User; | ||
import org.springframework.transaction.support.TransactionTemplate; | ||
|
||
public class TxUserService implements UserService { | ||
|
||
private final UserService userService; | ||
private final TransactionTemplate transactionTemplate; | ||
|
||
public TxUserService(UserService userService, TransactionTemplate transactionTemplate) { | ||
this.userService = userService; | ||
this.transactionTemplate = transactionTemplate; | ||
} | ||
|
||
@Override | ||
public User findById(long id) { | ||
return transactionTemplate.execute(() -> userService.findById(id)); | ||
} | ||
|
||
@Override | ||
public void insert(User user) { | ||
transactionTemplate.execute(() -> { | ||
userService.insert(user); | ||
return null; | ||
}); | ||
} | ||
|
||
@Override | ||
public void changePassword(long id, String newPassword, String createBy) { | ||
transactionTemplate.execute(() -> { | ||
userService.changePassword(id, newPassword, createBy); | ||
return null; | ||
}); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,38 +1,12 @@ | ||
package com.techcourse.service; | ||
|
||
import com.techcourse.dao.UserDao; | ||
import com.techcourse.dao.UserHistoryDao; | ||
import com.techcourse.domain.User; | ||
import com.techcourse.domain.UserHistory; | ||
import org.springframework.transaction.support.TransactionTemplate; | ||
|
||
public class UserService { | ||
public interface UserService { | ||
|
||
private final UserDao userDao; | ||
private final UserHistoryDao userHistoryDao; | ||
private final TransactionTemplate transactionTemplate; | ||
User findById(long id); | ||
|
||
public UserService(UserDao userDao, UserHistoryDao userHistoryDao, TransactionTemplate transactionTemplate) { | ||
this.userDao = userDao; | ||
this.userHistoryDao = userHistoryDao; | ||
this.transactionTemplate = transactionTemplate; | ||
} | ||
void insert(User user); | ||
|
||
public User findById(long id) { | ||
return userDao.findById(id); | ||
} | ||
|
||
public void insert(User user) { | ||
userDao.insert(user); | ||
} | ||
|
||
public void changePassword(long id, String newPassword, String createBy) { | ||
transactionTemplate.execute(() -> { | ||
var user = findById(id); | ||
user.changePassword(newPassword); | ||
userDao.update(user); | ||
userHistoryDao.log(new UserHistory(user, createBy)); | ||
return null; | ||
}); | ||
} | ||
void changePassword(long id, String newPassword, String createBy); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,19 @@ | ||
package org.springframework.jdbc.datasource; | ||
|
||
import org.springframework.jdbc.CannotGetJdbcConnectionException; | ||
import org.springframework.transaction.support.TransactionSynchronizationManager; | ||
|
||
import javax.sql.DataSource; | ||
import java.sql.Connection; | ||
import java.sql.SQLException; | ||
import javax.sql.DataSource; | ||
import org.springframework.jdbc.CannotGetJdbcConnectionException; | ||
import org.springframework.transaction.support.TransactionSynchronizationManager; | ||
|
||
// 4단계 미션에서 사용할 것 | ||
public abstract class DataSourceUtils { | ||
|
||
private DataSourceUtils() {} | ||
private DataSourceUtils() { | ||
} | ||
|
||
public static Connection getConnection(DataSource dataSource) throws CannotGetJdbcConnectionException { | ||
Connection connection = TransactionSynchronizationManager.getResource(dataSource); | ||
var connection = TransactionSynchronizationManager.getResource(dataSource); | ||
if (connection != null) { | ||
return connection; | ||
} | ||
|
@@ -28,8 +28,13 @@ public static Connection getConnection(DataSource dataSource) throws CannotGetJd | |
} | ||
|
||
public static void releaseConnection(Connection connection, DataSource dataSource) { | ||
if (TransactionSynchronizationManager.isActualTransactionActive()) { | ||
return; | ||
} | ||
Comment on lines
+31
to
+33
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. 외부에서 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. 우선 트랜잭션이 살아있는동안은 커넥션을 공유하고 있는 상태라고 판단했어요 🤓
하지만 단순히 따라서 트랜잭션이 존재하는 동안은 |
||
|
||
try { | ||
connection.close(); | ||
TransactionSynchronizationManager.unbindResource(dataSource); | ||
} catch (SQLException ex) { | ||
throw new CannotGetJdbcConnectionException("Failed to close JDBC Connection"); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,23 +1,41 @@ | ||
package org.springframework.transaction.support; | ||
|
||
import javax.sql.DataSource; | ||
import static java.lang.ThreadLocal.withInitial; | ||
|
||
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 = withInitial(HashMap::new); | ||
private static final ThreadLocal<Boolean> actualTransactionActive = withInitial(() -> false); | ||
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. 쓰레드 로컬에서 이런 초기화 함수도 지원해주는군요! 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; | ||
return getResources().get(key); | ||
} | ||
|
||
public static void bindResource(DataSource key, Connection value) { | ||
getResources().put(key, value); | ||
} | ||
|
||
public static Connection unbindResource(DataSource key) { | ||
return null; | ||
return getResources().remove(key); | ||
} | ||
|
||
private static Map<DataSource, Connection> getResources() { | ||
return resources.get(); | ||
} | ||
|
||
public static boolean isActualTransactionActive() { | ||
return actualTransactionActive.get(); | ||
} | ||
|
||
public static void setActualTransactionActive(boolean active) { | ||
actualTransactionActive.set(active); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,12 +12,12 @@ public TransactionTemplate(DataSource dataSource) { | |
|
||
public <T> T execute(TransactionCallBack<T> action) { | ||
try { | ||
transactionManager.startTransaction(); | ||
transactionManager.doGetTransaction(); | ||
T result = action.doInTransaction(); | ||
transactionManager.commit(); | ||
transactionManager.doCommit(); | ||
return result; | ||
} catch (RuntimeException | Error e) { | ||
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. 확실히 Error인 상황에도 롤백이 될 수 있도록 처리하면 좋겠네요! Error를 catch하여 뭔가 의미 있는 행동을 하는 케이스를 여기서 처음 본 것 같네요 ㅋㅋㅋㅋ 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. 스프링에서도 프레임워크를 학습하며 최대한 따라갈 수 있도록 구현해보았습니다 ! |
||
transactionManager.rollback(); | ||
transactionManager.doRollback(); | ||
throw e; | ||
} | ||
} | ||
|
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.
return값이 없는 경우를 위한
TransactionTemplate
메서드를 만들면 어떨까요?!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.
만들지 말지 고민했었는데 꼼꼼하게 집어주셨네요 ㅎㅎ
말씀해주신 것처럼
return
값이 필요로 하지 않을 때 사용할 수 있는 메서드가 있으면 좋을 것 같아요 👍