본문 바로가기
dev/Spring

[Spring] @Transactional-2

by dev_Step 2022. 7. 12.

Transcation의 속성

속성 설명
propagation Tx의 경계(Boundary)를 설정하는 방법을 저장
isolation Tx의 isolate level을 지정, DEFAUL, READ_UMCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
Default의 경우 DB설정을 따른다(Default = REPEATABLE_READ)
readOnly Tx이 데이터를 읽기만 하는경우, true로 지정하면 성능이 향상
rollbackFor 지정된 예외가 발생하면, Tx를 rollback // RuntimeException과 Error는 자동 rollback
noRollbackFor 지정된 예외가 발생해도, Tx을 Rollback하지 않음
timeout 지정된 시간(초) 내에 Tx이 종료되지 않으면, Tx를 강제종료

 

propagation 속성의 값

설명
REQUIRED Tx이 진행중이면 참여하고, 없으면 새로운 Tx시작(디폴트)
REQUIREDS_NEW Tx이 진행 중이건 아니건, 새로운 Tx 시작 ( Tx안에 다른 Tx 생성)
NESTED Tx이 진행 중이면, Tx의 내부 Tx로 실행     ( Tx안에 subTx같은 Tx생성) - save point
MANDATORY 반드시 진행 중인 Tx 내에서만 실행가능, 아니면 예외발생
SUPPORTS Tx이 진행중이건 아니건 상관없이 실행
NOT_SUPPORTED Tx없이 처리. Tx이 진행 중이면 잠시 중단(suspend)
NEVER Tx없이 처리. Tx이 진행중이면 예외발생

 

>> REQUIRED  ==> Default   // @Transactional(propagation = Propagation.REQUIRED)

   - 1개의 트랜잭션으로 처리하며, 오류 발생시 처음으로 Rollback 된다.

 

>> REQUIREDS_NEW -- 2개의 Tx 생성된다.            // @Transactional(propagation = Propagation.REQUIRED_NEW)

>> A1, B1,B2 성공했을때 A2가 실패했을경우 A1은 Rollback 되지만 

>> B1,B2는 별개의 작업이므로 Rollback 되지 않는다.

 

 

>> REQUIRED 의 경우 ERROR 발생시 처음으로 ROLLBACK된다. 즉 DB에 COMMIT되지 않았다.

 

>> REQUIRED_NEW

>> insertB1WithTx()의 경우는 다른 Tx이므로  Rollback 되지 않고 commit된다.

>> @Transactional 어노테이션을 사용하니 같은 클래스 내의 메서드로 해당 REQURED_NEW, REQURED 확인하려고 하니 한개의 conn으로 나온다

>> 그래서 직접 Tx의 경계를 나눠주고 실행해 봤다.

>> conn이 분리되어 실행되는 것을 확인할 수 있다 (propagaing = REQUIRES_NEW)

>> 즉 insertB1WithTx() 의 실행결과는 다른 Tx로 진행된것이므로 Rollback 되지 않고 commit되었고,

     a1dao.insert(1,100), a1dao.insert(1,200)은 Rollback 되어 commit되지 않았다.

========================================================================================

 

>> @Transactional  의 사용

 

[1,2] 의경우 primary key 때문에 중복 에러가 발생하게 됩니다.

 

1. insertA1WithoutTx() 

  >> insert 실행중 예외 발생시 insert 된것은 commit 되고 나머지는 commit 되지 않음

 

2. insertA1WithoutFail()

  >> (1) @Transactional   어노테이션을 붙였을경우

           - RuntimeException , Error만 Rollback 을 해주기 때문에 다른 예외가 발생할 경우 1.과 동일한 결과

  >> (2) @Transactional(rollbackFor = Exception.class)

           -  Rollback의 범위를 지정하는것으로, Exception 의 자손 예외까지 모두 Rollback 시켜준다.

 

3. insertA1WithoutSuccess()

  >> 정상적으로 실행된다. 

@Service
public class TxService {
    @Autowired   a1DAO a1dao;
    @Autowired   B1DAO b1dao;

    public void insertA1WithoutTx() throws Exception{
        a1dao.insert(1,100);
        a1dao.insert(1,200);
    }

//    @Transactional(rollbackFor = Exception.class) // Exception을 rollback
    @Transactional // RuntimeException, Error 만 rollback
    public void insertA1WithoutFail() throws Exception{
        a1dao.insert(1,100);
        throw new Exception();
        //a1dao.insert(1,200);
    }

    @Transactional
    public void insertA1WithoutSuccess() throws Exception{
        a1dao.insert(1,100);
        a1dao.insert(2,200);
    }

}

 

>> Test 코드

package com.fastcampus.ch3;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import static org.junit.Assert.*;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"file:src/main/webapp/WEB-INF/spring/root-context.xml"})
public class TxServiceTest {

    @Autowired
    TxService txService;

    @Test
    public void insertA1WithoutTx() throws Exception{
        txService.insertA1WithoutFail();
        //  txService.insertA1WithoutSuccess();
        //  txService.insertA1WithoutTx();
    }

}

 

 

즉  @Transactional 을 사용할 경우 서비스 로직에서 아래와같은 try-catch 문을 자동으로 생성하여 비지니스로직 전, 후로 적용해준다.

 

 

 

'dev > Spring' 카테고리의 다른 글

[Spring] Paging  (0) 2022.07.13
[Spring] Mybatis -1 (2방법)  (0) 2022.07.12
[Spring] @Transactional-1  (0) 2022.07.12
[Spring] AOP-2  (0) 2022.07.12
[Spring] Transaction, Commit, Rollback  (0) 2022.07.06