-
Notifications
You must be signed in to change notification settings - Fork 379
[4단계 - Transaction synchronization 적용하기] 폰트(김영재) 미션 제출합니다. #1164
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
base: yeong0jae
Are you sure you want to change the base?
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,30 @@ | ||
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(final UserDao userDao, final UserHistoryDao userHistoryDao) { | ||
this.userDao = userDao; | ||
this.userHistoryDao = userHistoryDao; | ||
} | ||
|
||
@Override | ||
public User findById(final long id) { | ||
return userDao.findById(id); | ||
} | ||
|
||
@Override | ||
public void changePassword(final long id, final String newPassword, final String createdBy) { | ||
final var user = userDao.findById(id); | ||
user.changePassword(newPassword); | ||
userDao.update(user); | ||
userHistoryDao.log(new UserHistory(user, createdBy)); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package com.techcourse.service; | ||
|
||
import com.interface21.dao.DataAccessException; | ||
import com.interface21.jdbc.datasource.DataSourceUtils; | ||
import com.interface21.transaction.support.TransactionSynchronizationManager; | ||
import com.techcourse.domain.User; | ||
|
||
import javax.sql.DataSource; | ||
import java.sql.Connection; | ||
import java.sql.SQLException; | ||
|
||
public class TxUserService implements UserService { | ||
|
||
private final UserService userService; | ||
private final DataSource dataSource; | ||
|
||
public TxUserService(final UserService userService, final DataSource dataSource) { | ||
this.userService = userService; | ||
this.dataSource = dataSource; | ||
} | ||
|
||
@Override | ||
public User findById(final long id) { | ||
return userService.findById(id); | ||
} | ||
|
||
@Override | ||
public void changePassword(final long id, final String newPassword, final String createdBy) { | ||
Connection connection = DataSourceUtils.getConnection(dataSource); | ||
try { | ||
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.
|
||
connection.setAutoCommit(false); | ||
|
||
try { | ||
userService.changePassword(id, newPassword, createdBy); | ||
connection.commit(); | ||
} catch (Exception e) { | ||
try { | ||
connection.rollback(); | ||
} catch (SQLException rollbackEx) { | ||
e.addSuppressed(rollbackEx); | ||
} | ||
throw new DataAccessException("Failed to change password for user id: " + id, e); | ||
} | ||
} catch (SQLException e) { | ||
throw new DataAccessException("Failed to manage transaction", e); | ||
} finally { | ||
TransactionSynchronizationManager.unbindResource(dataSource); | ||
DataSourceUtils.releaseConnection(connection, dataSource); | ||
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.
|
||
} | ||
Comment on lines
+28
to
+49
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. 트랜잭션 소유권(ownership)과 중첩 트랜잭션 참여(propagation) 미정의 현재 구현은 다음 두 가지 위험이 있습니다.
질문/힌트
🤖 Prompt for AI Agents
|
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,56 +1,9 @@ | ||
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 javax.sql.DataSource; | ||
import java.sql.Connection; | ||
import java.sql.SQLException; | ||
public interface UserService { | ||
|
||
public class UserService { | ||
|
||
private final UserDao userDao; | ||
private final UserHistoryDao userHistoryDao; | ||
private final DataSource dataSource; | ||
|
||
public UserService(final UserDao userDao, final UserHistoryDao userHistoryDao, final DataSource dataSource) { | ||
this.userDao = userDao; | ||
this.userHistoryDao = userHistoryDao; | ||
this.dataSource = dataSource; | ||
} | ||
|
||
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) { | ||
try (Connection connection = dataSource.getConnection()) { | ||
connection.setAutoCommit(false); | ||
|
||
try { | ||
final var user = userDao.findById(connection, id); | ||
user.changePassword(newPassword); | ||
userDao.update(connection, user); | ||
userHistoryDao.log(connection, new UserHistory(user, createBy)); | ||
|
||
connection.commit(); | ||
} catch (Exception e) { | ||
try { | ||
connection.rollback(); | ||
} catch (SQLException rollbackEx) { | ||
e.addSuppressed(rollbackEx); | ||
} | ||
throw new DataAccessException("Failed to change password for user id: " + id, e); | ||
} | ||
} catch (SQLException e) { | ||
throw new DataAccessException("Failed to get connection", e); | ||
} | ||
} | ||
User findById(final long id); | ||
void changePassword(final long id, final String newPassword, final String createdBy); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,7 @@ | |
|
||
import javax.sql.DataSource; | ||
import java.sql.Connection; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
public abstract class TransactionSynchronizationManager { | ||
|
@@ -11,13 +12,31 @@ public abstract class TransactionSynchronizationManager { | |
private TransactionSynchronizationManager() {} | ||
|
||
public static Connection getResource(DataSource key) { | ||
return null; | ||
Map<DataSource, Connection> map = resources.get(); | ||
if (map == null) { | ||
return null; | ||
} | ||
return map.get(key); | ||
} | ||
|
||
public static void bindResource(DataSource key, Connection value) { | ||
Map<DataSource, Connection> map = resources.get(); | ||
if (map == null) { | ||
map = new HashMap<>(); | ||
resources.set(map); | ||
} | ||
map.put(key, value); | ||
} | ||
Comment on lines
22
to
29
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. 중복 바인딩에 대한 처리를 고려해보셨나요? 현재 고려할 점:
힌트: if (map.containsKey(key)) {
// 이미 바인딩된 경우 처리
} 🤖 Prompt for AI Agents
|
||
|
||
public static Connection unbindResource(DataSource key) { | ||
return null; | ||
Map<DataSource, Connection> map = resources.get(); | ||
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.
|
||
if (map == null) { | ||
return null; | ||
} | ||
Connection connection = map.remove(key); | ||
if (map.isEmpty()) { | ||
resources.remove(); | ||
} | ||
return connection; | ||
} | ||
} |
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.
필드로 UserService 들고있는 이상 impl 할 필요없을 것 같은데, 어떻게 생각하시나요?