@Transactional

TopOfTheHead·5일 전

Spring Boot

목록 보기
26/26

@Transactional : org.springframework.transaction.annotation
DB트랜잭션을 수행할때 원자성을 보장하기 위해 경계를 설정하여 commit / rollback을 자동으로 관리하는 기능이 추상화어노테이션
호출이 정상종료 시 commit, 예외 발생 시 rollback하여 원자성을 보장

Spring BeanService Class내에서 사용되므로 jakarta가 아닌 Spring@Transactional을 사용

AOP를 기반으로 구현된 어노테이션으로서 EntityManagerEntityTransaction 객체추상화하여 구현됨
tx객체.begin(), tx객체.commit(), tx객체.rollback() 등의 TCL을 자동으로 수행

Production Code가 아닌 Test Code에서 테스트 클래스클래스 레벨에 선언하는 경우 Test가 끝난경우 자동으로 DB를 다시 Transaction 수행 이전으로 Rollback하므로 자원을 해제할 필요가 없다
▶ 이때 클래스명 뒤에 Test 키워드가 붙어야한다. ( ex. UserTest.java )

Service Class에서 JpaRepository에 의해 Entity를 통한 CRUD가 구현된 메서드 레벨에서 선언
클래스 레벨에서 선언하여 Service Class내 모든 메서드@Transactional을 일괄적으로 적용 가능

  • 어플리케이션 트랜잭션DB 트랜잭션을 별도 개념
    어플리케이션트랜잭션은 실제 비즈니스 서비스 작업단위로서 서비스 계층 @Transactional이 적용된 메서드에 해당
    ex ) Post 수정의 경우 Post를 찾고, 수정하는 2개의 작업을 하나의 서비스 작업단위로 지정

    DB 트랜잭션DB상호작용하는 행위를 수행하는 개별 작업단위로서 Repository계층@Transactional 메서드에 해당
    ex ) Post 수정에서 각각 Post를 찾는 작업 / Post를 수정하는 작업은 각각 별개의 작업단위

  • @Transactional(readOnly = true) 기본 : false : org.springframework.transaction.annotation.Transactional의 기능
    트랜잭션쓰기 작업 발생 시 절대 반영하지않고, 오직 읽기 작업만 수행하도록 설정하여 읽기 작업 전용 메서드로 전환하는 어노테이션
    @Transactional(readOnly=true)를 선언할 경우 Dirty Checking의 작동이 차단되어 Entity수정되더라도 DB Table에 반영되지않음

    。실무에서는 서비스 계층클래스 레벨@Transactional(readOnly = true)를 선언하고, 내부 쓰기작업을 수행하는 메서드에 대해서는 @Transactional(readOnly = false)를 선언
 @Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class OrderService {
    private final OrderRepository orderRepository;
    //
    @Transactional(readOnly = false)
    public Orders saveOrders(Orders orders){
        return orderRepository.saveOrders(orders);
    }
    //
    @Transactional(readOnly = false)
    public OrderItem saveOrderItems(OrderItem orderitem){
        return orderRepository.saveOrderItems(orderitem);
    }
}
  • @Transactional(propagation = Propagation.REQUIRES_NEW)
    。복수의 트랜잭션호출관계에 따라서 기존 트랜잭션을 그대로 이어서 할건지, 새로 트랜잭션을 생성할지를 결정

    REQUIRES_NEW : 항상 새 트랜잭션을 생성하며 기존 트랜잭션이 존재하는 경우 일시중단
    트랜잭션독립을 보장

    @Transactional 원리

    private final PlatformTransactionManager transactionManager;
    	public void createMember(MemberCreateRequest request){
    		var transaction = transactionManager.getTransaction(new DefaultTransactionAttribute());
    		try{
    			var member = new MemberEntity(
    				//
    			);
    			memberRepository.save(member);
    		}catch(Exception e){
    			// 실패 시 롤백
    			transactionManager.rollback(transaction);
    		}
    		// 커밋
    		transactionManager.commit(transaction);
    	}

    DBTransaction을 수행 시 원자성을 보장하기위해 transactionManager를 통한 commitrollback을 수행하는 코드를 일일히 지정

    @Transactional // 트랜잭션의 원자성 보장
    	public void createMember(MemberCreateRequest request){
    		var member = new MemberEntity(
    			//
    		);
    		memberRepository.save(member);
    	}

    ▶ 해당 과정을 단순하게 메서드 레벨에서 @Transactional을 선언하여 원자성을 보장가능

테스트 코드에서의 @Transactional
Production 코드에서는 DB Transaction 실패 시 DB Entity 상태트랜잭션 전으로 Rollback하는 용도의 어노테이션
@Transactional에 의해 DB Rollback을 보장하므로 자원해제를 수행하는 @AfterEach 메서드는 선언하지 않아도 된다.

테스트 코드에서 테스트 클래스클래스 레벨에 선언하는 경우 Test가 끝난경우 자동으로 DB를 다시 Transaction 수행 전으로 Rollback
▶ 이때 클래스명 뒤에 Test 키워드가 붙어야한다. ( ex. UserTest.java )

@DataJpaTestTransaction초기화가 자동으로 되므로 @SpringBootTest에 선언

。단. 비동기 테스트에서는 @Transactional 이 충돌되므로 @AfterEach method를 통해 자원해제를 수행.

profile
공부기록 블로그

0개의 댓글