@Transactional

iseon_u·2023년 5월 8일
0

Spring

목록 보기
32/33
post-thumbnail

TransactionManager

  • 기존엔 DAO 의 각 메서드는 개별 Connection 을 사용
    • 1 Connection 에 1 Tx
    • 오류가 발생하여 롤백 처리해도 다른 Connection 은 롤백이 안된다.
  • → 같은 Tx 내에서 같은 Connection 을 사용할 수 있게 관리

TransactionManager 로 Transaction 적용

public void insertWithTx() throws Exception {
		// TxManager 생성
		PlatformTransactionManager tm = new DataSourceTransactionManager(ds);
		TransactionStatus status = tm.getTransaction(new DefaultTransactionDefinition());
		// Tx 시작

		try {
				dao.insert(1,100); // 원래는 개별 Connection
				dao.insert(1,200); // TxManager 가 같은 Connection 으로 묶어준다.
				tm.commit(status); // Tx 끝 - 성공 (커밋)
		} catch(Exception ex) {
				tm.rollback(status); // Tx 끝 - 실패 (롤백)
		}
}
  • 핵심 기능
    • dao.insert(1,100);
  • 부가 기능
    • Tx 관련 코드
    • 불변하는 코드
    • 코드 중복 발생
    • AOP 필요

@Transactional

  • AOP 를 이용한 핵심 기능과 부가 기능의 분리
@Transactional
public void insertWithTx() throws Exception {
		dao.insert(1,100);
		dao.insert(1,200);
}
  • 부가 기능 코드를 @Transactional 어노테이션으로 대체
    • 핵심 로직에만 집중하면 된다.
  • 클래스나 인터페이스에도 @Transactional 어노테이션 가능
  • RuntimeException 과 Error 만 rollback 처리
    • Checked Exception에 대해서는 롤백시키지 않도록 설계 🚨
    • 스프링 프레임워크가 EJB 관습을 따르기 때문
  • @Transactional(rollbackFor = Exception.class)
    • Exception 과 그 자손들 처리

@Transactional 의 속성

속성설명
propagationTx 의 경계 (boundary) 를 설정하는 방법을 지정
isolationTx 의 isolation level 을 지정 DEFAULT, READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
readOnlyTx 이 데이터를 읽기만 하는 경우 true 로 지정하면 성능이 향상
rollbackFor지정된 예외가 발생하면 Tx 을 rollback
RuntimeException 과 Error 는 자동 rollback
noRollbackFor지정된 예외가 발생해도 Tx 을 rollback 하지 않는다.
timeout지정된 시간 (초) 내에 Tx 이 종료되지 않으면 Tx 을 강제 종료

propagation 속성 값

설명
REQUIREDTx 이 진행 중이면 참여하고 없으면 새로운 Tx 시작 (디폴트)
REQUIRES_NEWTx 이 진행 중이건 아니건 새로 Tx 시작
NESTEDTx 이 진행 중이면, Tx 의 내부 Tx 로 실행
MANDATORY반드시 진행 중인 Tx 내에서만 실행 가능 아니면 예외 발생
SUPPORTSTx 이 진행 중이건 아니건 상관 없이 실행
NOT_SUPPORTEDTx 없이 처리 Tx 이 진행 중이면 잠시 중단 (suspend)
NEVERTx 없이 처리 Tx 이 진행 중 이면 예외 발생

REQUIRED

@Transactional(propagation = Propagation.REQUIRED)
public void insertA1WithTx() throws Exception {
		a1Dao.insert(1,100);
		insertB1WithTx();
		a1Dao.insert(1,200);
}
@Transactional(propagation = Propagation.REQUIRED)
public void insertB1WithTx() throws Exception {
		b1Dao.insert(1,100);
		b1Dao.insert(1,200);
}
  • Tx 이 진행 중이면 참여하고 없으면 새로운 Tx 시작 (디폴트)
  • 중간에 에러가 발생하면 다같이 rollback

REQUIRES_NEW

@Transactional(propagation = Propagation.REQUIRED)
public void insertA1WithTx() throws Exception {
		a1Dao.insert(1,100);
		insertB1WithTx();
		a1Dao.insert(1,200);
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void insertB1WithTx() throws Exception {
		b1Dao.insert(1,100);
		b1Dao.insert(1,200);
}
  • Tx 이 진행 중이건 아니건 새로 Tx 시작
  • 예제에서는 서로 다른 2개의 Tx
  • 만약 A2 에서 에러 발생시 A1 rollback
    • B1, B2 는 다른 Tx 이기 때문에 영향이 없다.

프록시 방식 (디폴트) 의 AOP 는 내부 호출인 경우 Advice 가 적용 되지 않기 때문에 따로 Tx 가 적용되지 않는다.

두 메서드를 별도의 클래스로 분리 하거나 AOP 를 프록시 방식이 아닌 다른 방식으로 처리해야 예제처럼 Tx 적용

profile
🧑🏻‍💻 Hello World!

0개의 댓글