- TxManager를 직접 생성하지 않고 주입받아서 처리해보자.
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<tx:annotation-driven/>
해당 코드를 root-context.xml에 넣어준다. TxManager를 빈으로 넣어준것이다.

TxManager를 생성하는 문장 대신 위에 선언해준 후 테스트를 돌려도 테스트가 통과한다면 잘 설정한 것이다.

테스트도 통과하고 데이터도 잘 주입되었다.
- 새로운 테이블 생성
create table b1 select * from a1 where false; # 테이블만 생성
create table b1 select * from a1; # 테이블 생성 & 데이터 복사
데이터를 복사한 테이블을 생성했다.
- A1Dao 클래스를 복사해서 B1Dao 클래스와 TxService 클래스 생성.



-> 강의대로 했는데.. 커넥션 생성도 안되고 테이블에 데이터도 들어가지 않는다.. 무제한 에러 ㅠㅠㅠ
TxService와 TxServiceTest 수행 과정에서 문제가 있는 것 같다..
5. @Transactional의 속성
| 속성 | 설명 |
| propagation | Tx의 경계(boundary)를 설정하는 방법을 지정 |
| isolation | Tx의 isolation level을 지정. DEFAULT, READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE |
| readOnly | Tx의 데이터를 읽기만 하는 경우, true로 지정하면 성능이 향상 |
| rollbackFor | 지정된 예외가 발생하면, Tx을 rollback RuntimeException과 Error는 자동 rollback |
| noRollbackFor | 지정된 예외가 발생해도, Tx을 rollback하지 않음 |
| timeout | 지정된 시간(초) 내에 Tx이 종료되지 않으면, Tx를 강제 종료 |
6. propagation속성의 값
| 값 | 설명 |
| REQUIRED | Tx이 진행중이면 참여하고, 없으면 새로운 Tx 시작(디폴트) |
| REQUIRES_NEW | Tx이 진행 중이건 아니건, 새로 Tx 시작(Tx안에 다른 Tx) |
| NESTED | Tx이 진행 중이면, Tx의 내부 Tx로 실행(Tx안에 subTx. 실제로는 같은 Tx안에서 처리) |
| MANDATORY | 반드시 진행 중인 Tx내에서만 실행가능. 아니면 예외 발생 |
| SUPPORTS | Tx이 진행 중이건 아니건 상관없이 실행 |
| NOT_SUPPORTED | Tx없이 처리. Tx이 진행 중이면 잠시 중단(suspend) |
| NEVER | Tx없이 처리. Tx이 진행 중이면 예외 발생 |
7. REQUIRED와 REQUIRES_NEW (1) - REQUIRED
// 1.
@Transactional(propagation = Propagation.REQUIRED)
public void insertA1WithTx() throws Exception {
a1Dao.insert(1,100); // A1
insertB1WithTx();
a1Dao.insert(1,200); // A2
}
// 2.
@Transactional(propagation = Propagation.REQUIRED)
public void insertB1WithTx() throws Exception {
b1Dao.insert(1,100); // B1
b1Dao.insert(1,200); // B2
}
1번이 2번을 호출하는 것이다.
REQUIRED는 일단 트랜잭션을 실행하고, A1을 insert한다. 그 다음 2번을 호출하고 B1과 B2를 실행한다음
다시 A2 작업을 실행한다.
호출할 때 REQUIRED이면 Tx가 기존에 있으면 새로 Tx를 만들지 않는다.

예외가 발생했을 때 Tx1 시작까지 rollback이 이루어진다.
7. REQUIRED와 REQUIRES_NEW (2) - REQUIRED_NEW
// 1.
@Transactional(propagation = Propagation.REQUIRED)
public void insertA1WithTx() throws Exception {
a1Dao.insert(1,100); // A1
insertB1WithTx();
a1Dao.insert(1,200); // A2
}
// 2.
@Transactional(propagation = Propagation.REQUIRED_NEW)
public void insertB1WithTx() throws Exception {
b1Dao.insert(1,100); // B1
b1Dao.insert(1,200); // B2
}
REQUIRED_NEW는 새로운 Tx을 필요로 한다.

새로운 Tx을 만들기 때문에 B1을 시작하면서 새로운 Tx가 생긴다.
2개의 Tx이 존재하게 된다.
B2쪽에서 예외가 발생하면 Tx2 시작 부분까지 rollback이 이루어지고, A2에서 예외가 발생하면 Tx1 시작 부분까지
rollback이 수행된다.
이 때 B1,B2의 성공한 작업은 취소가 되지 않고 commit이 된다. (별도의 트랜잭션)
'Spring' 카테고리의 다른 글
| ch4 01. MyBatis의 소개와 설정 (0) | 2023.03.16 |
|---|---|
| ch3 21. 서비스 계층의 분리와 @Transactional(3) (0) | 2023.03.15 |
| ch3 19. 서비스 계층의 분리와 @Transactional(1) (0) | 2023.03.15 |
| ch3 18. AOP의 개념과 용어 (0) | 2023.03.14 |
| ch3 17. Transaction, Commit, Rollback (0) | 2023.03.14 |