Skip to content
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단계] 성하(김성훈) 미션 제출합니다. #489

Merged
merged 12 commits into from
Oct 11, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions app/src/main/java/com/techcourse/service/TxUserService.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ public class TxUserService implements UserService {
private final UserService userService;
private final TransactionExecutor transactionExecutor;

public TxUserService(final UserService userService) {
this.userService = userService;
public TxUserService(final AppUserService appUserService) {
this.userService = appUserService;
this.transactionExecutor = new TransactionExecutor(DataSourceConfig.getInstance());
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
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 {
Expand All @@ -29,6 +28,7 @@ public static Connection getConnection(DataSource dataSource) throws CannotGetJd

public static void releaseConnection(Connection connection, DataSource dataSource) {
try {
TransactionSynchronizationManager.unbindResource(dataSource);
connection.close();
} catch (SQLException ex) {
throw new CannotGetJdbcConnectionException("Failed to close JDBC Connection");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import javax.sql.DataSource;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.transaction.support.TransactionSynchronizationManager;

public class TransactionExecutor {

Expand All @@ -32,18 +31,17 @@ public void execute(final ServiceExecutor serviceExecutor, final boolean isReadO
}
} finally {
DataSourceUtils.releaseConnection(connection, dataSource);
TransactionSynchronizationManager.unbindResource(dataSource);
}
}

public <T> T execute(final ServiceCallback<T> serviceExecutor, boolean isReadOnly) {
public <T> T execute(final ServiceCallback<T> serviceCallback, boolean isReadOnly) {
Connection connection = DataSourceUtils.getConnection(dataSource);

try {
connection.setAutoCommit(false);
connection.setReadOnly(isReadOnly);

T result = serviceExecutor.doInAction();
T result = serviceCallback.doInAction();

connection.commit();
return result;
Expand All @@ -55,7 +53,6 @@ public <T> T execute(final ServiceCallback<T> serviceExecutor, boolean isReadOnl
}
} finally {
DataSourceUtils.releaseConnection(connection, dataSource);
TransactionSynchronizationManager.unbindResource(dataSource);
}
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,38 @@ public abstract class TransactionSynchronizationManager {
private TransactionSynchronizationManager() {}

public static Connection getResource(DataSource key) {
if (resources.get() == null) {
Map<DataSource, Connection> connectionMap = resources.get();
if (connectionMap == null) {
return null;
}
Map<DataSource, Connection> connectionMap = resources.get();
return connectionMap.get(key);
}

public static void bindResource(DataSource key, Connection value) {
Map<DataSource, Connection> connectionMap = new HashMap<>();
Map<DataSource, Connection> connectionMap = resources.get();
if (connectionMap == null) {
connectionMap = new HashMap<>();
resources.set(connectionMap);
}

Connection mappedConnection = connectionMap.put(key, value);
if (mappedConnection != null) {
throw new IllegalStateException("fail to bind resource because of already exist bound thread");
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

현재 connectinMap에서 값을 넣고 올바르지 않으면 예외를 터트려주고있지만 잘못된 값은 map에 들어가게 되는 같아요
그래서 값을 넣기전에 먼저 검증을해주는건 어떨까요??

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

해당 부분은 넣은 값이 올바르지 않으면 예외를 터트려주는 것이 아니라
넣은 값이 이미 존재한다면 예외를 터트려주는 것으로 이해하시면 될 것 같아요!

Connection mappedConnection = connectionMap.put(key, value);에서 나오면
mappedConnection은 해당 key에 해당하는 value가 존재한다면 존재하는 value를 반환하고,
key에 해당하는 value가 없다면 Map에 key, value를 넣고 null이 들어가게 됩니다!

그래서 예외를 발생시키는 이유가, 이미 ConnectionMap에 DataSource에 해당하는 Connection이 존재한다면
이미 스레드에 bind된 Resource가 있는 것이므로 예외를 발생시켰습니다!

그래서 결론적으로 put을 한 결과가 if 검증에서 필요해서 순서는 저대로 해야하는 것 같아요!

resources.set(connectionMap);
}

public static Connection unbindResource(DataSource key) {
Map<DataSource, Connection> connectionMap = resources.get();
Connection connectionToRemove = connectionMap.get(key);
resources.remove();
if (connectionMap == null) {
return null;
}
Connection connectionToRemove = connectionMap.remove(key);
if (connectionToRemove == null) {
throw new IllegalStateException("fail to unbind resource because of not found value");
}
if (connectionMap.isEmpty()) {
resources.remove();
}
return connectionToRemove;
}
}
Loading