@Transactional:org.springframework.transaction.annotation
。DB에트랜잭션을 수행할때원자성을 보장하기 위해경계를 설정하여commit / rollback을 자동으로 관리하는 기능이추상화된어노테이션
▶호출이 정상종료 시commit,예외발생 시rollback하여원자성을 보장
。Spring Bean인Service Class내에서 사용되므로jakarta가 아닌Spring의@Transactional을 사용
。AOP를 기반으로 구현된어노테이션으로서EntityManager의 EntityTransaction 객체를추상화하여 구현됨
▶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); }。
DB에Transaction을 수행 시원자성을 보장하기위해transactionManager를 통한commit과rollback을 수행하는코드를 일일히 지정@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)
。@DataJpaTest는Transaction후초기화가 자동으로 되므로@SpringBootTest에 선언
。단.비동기 테스트에서는@Transactional이 충돌되므로@AfterEach method를 통해자원해제를 수행.