-
Notifications
You must be signed in to change notification settings - Fork 0
6주차 #6
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: main
Are you sure you want to change the base?
The head ref may contain hidden characters: "6\uC8FC\uCC28"
Conversation
fail("TetUserSericeException expected"); | ||
} catch (TestUserServiceException e) { | ||
} | ||
checkLevelUpgraded(users.get(1), false); |
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.
p353. 테스트는 실패한다.
모든 사용자의 레벨을 업그레이드하는 작업인 upgradeLevels()
메소드가 하나의 트랜잭션 안에서 동작하지 않았기 때문이다.
트랜잭션이란 더 이상 나눌 수 없는 단위 작업을 말한다. (트랜잭션의 핵심 속성인 원자성)
p. 353
작업별 트랜잭션 정의 👉🏻 더이상 쪼개질 수 없는지! |
데이터 액세스 코드를 DAO로 만들어서 분리해놓았을 경우에는 이처럼 DAO 메서드를 호출할 때마다 하나의 새로운 트랜잭션이 만들어지는 구조가 될 수 밖에 없다. (jdbc api를 직접 사용하든, JdbcTemplate을 이용하든) // JdbcTemplate에서 sql을 실행할 때 사용하는 메서드
private <T> T execute(PreparedStatementCreator psc, PreparedStatementCallback<T> action, boolean closeResources) throws DataAccessException {
// ...
Connection con = DataSourceUtils.getConnection(this.obtainDataSource());
PreparedStatement ps = null;
// ...
} |
그럼? UserService 트랜잭션 경계설정의 문제점
|
+) 이 과정에서 예외가 발생하는 때에는 Connection.rollback()을 호출 후 동기화저장소에서 Connection 객체 제거. 트랜잭션 동기화 저장소는 작업 스레드마다 독립적으로 Connection 객체를 저장하고 관리하기 때문에 멀티스레드 환경에서도 충돌이 날 염려는 없다. |
이렇게 우리가 따로 JdbcTemplate은 수정할 필요도, 다른 요청을 할 필요도 없으므로 비즈니스 로직 레벨의 트랜잭션을 적용했지만 |
PlatformTransactionManager 를 이용하여 데이터액세스계층에 대한 종속성을 제거했다. datasource를 통해 각기 다른 transaction manager를 동작시킬 수 있다.
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.
스프링의 트랜잭션 서비스 추상화 (PlatformTransactionManager)
protected void upgradeLevel(User user) { | ||
if (user.getId().equals(this.id)) { | ||
throw new TestUserServiceException(); | ||
} | ||
super.upgradeLevel(user); | ||
} |
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에서 protected
접근자로 수정한 덕분에 upgradeLevel을 원하는대로 변경할 수 있게 되었다.
c.setAutoCommit(false); | ||
public void upgradeLevels() { | ||
PlatformTransactionManager transactionManager = new DataSourceTransactionManager(dataSource); | ||
TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition()); |
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.
transaction을 시작한다는 의미라고 생각하자.
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.
트랜잭션이 TransactionStatus
타입의 변수에 저장된다.
try { | ||
List<User> users = userDao.getAll(); | ||
for (User user : users) { | ||
upgradeLevel(user); | ||
} | ||
c.commit(); | ||
transactionManager.commit(status); |
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.
트랜잭션에 대한 조작이 필요할 때 PlatformTransactionManager의 메서드에 트랜잭션을 인자로 전달해주면 된당.
} finally { | ||
DataSourceUtils.releaseConnection(c, dataSource); | ||
TransactionSynchronizationManager.unbindResource(this.dataSource); | ||
TransactionSynchronizationManager.clearSynchronization(); |
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.
질문. 이런 건 transactionManager가 따로 안해줘도 되는건가
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.
답변. 응 . commit() 이랑 rollback()에 relase 로직이 포함돼있어
PlatformTransactionManager 변수에 구현체가 바뀔때마다 코드가 변경됐었다. 구현 클래스의 변경에 열려있지만 변경되지 않는 코드를 작성하기 위해 UserService에 DI 해서 사용한다.
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는 트랜잭션 기술에서 완전히 독립적인 코드가 됐다.
DAO가 하이버네이트, JPA, JDO 등을 사용하도록 수정한다해도,
UserService의 코드는 수정할 필요가 없다.
<bean id="transactionManager" | ||
class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> |
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.
구현체를 바꾸고 싶으면 여기에서 클래스를 바꿔주면 된다.
ex) JTA 를 사용하고 싶은 경우
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- ...빈 주입 -->
</bean>
이런식으로 바꾸면 된당.
수평적인 구분- |
dao의 add()와 update() 도 함께 수정
No description provided.