
@Transactional 어노테이션은 아래의 글에서 설명했듯이 직접 객체를 만들 필요 없이 선언만 해주면 해당 범위 내 메서드가 트랜젝션이 되도록 보장해주는 어노테이션이다.
만약 springBoot를 사용한다면 @Transactional 어노테이션에 여러가지 설정이 되어있기 때문에 더 쉽게 사용할 수 있다.
만약 @Transactional 어노테이션이 붙은 메서드를 호출할 경우 일단 @Transactional 어노테이션이 붙은 메서드는 spring에서는 해당 메서드에 대한 프록시를 만든다. 여기서 프록시는 프록시 패턴을 말하고 프록시 패턴은 디자인 패턴 중 하나로 대상 원본 객체를 대리하여 대신 처리하게 함으로써 로직의 흐름을 제어하는 행동 패턴이다.
https://inpa.tistory.com/entry/GOF-💠-프록시Proxy-패턴-제대로-배워보자#프록시_패턴_구조
(프록시 패턴을 자세히 알고 싶으면 해당게시글을 참고 바란다. 이거 이상 정리가 잘된 것은 찾지 못했다.)
스프링 컨테이너에서는 트랜잭션 범위의 영속성 컨텍스트 전략을 기본으로 사용한다.
서비스 클래스에서 @Transactional 어노테이션을 사용할 경우 해당 코드내에서 영속성 컨텍스트가 생긴다, 영속성 컨텍스트는 트랜잭션이 시작할 때 생성이되고, 메서드가 종료되어 최종적으로 영속성 컨텍스트에서 flush되고 commit혹은 rollback이 되면서 해당 내용이 반영된다, 이후 영속성 컨텍스트는 종료된다.
(김영한님의 [자바ORM표준 JPA프로그래밍] 579p 인용)
또한 트랜젝션을 사용한다면 아래의 원칙을 유의해야한다.
Spring이 제공하는 @Transactional 어노테이션의 장점중 하나는 여러 트랜잭션을 묶어서 커다란 하나의 트랜잭션 경계를 만들 수 있다는 점이다. 만약 기존에 트랜잭션이 진행중일 때 추가적으로 진행해야 하는 경우가 있다. 이미 트랜잭션이 진행중일 때 추가 트랜잭션을 어떻게 할지 결정하는 것을 전파 속성(Propagation) 이라고 한다.
전파 속성에 따라 기존의 트랜잭션에 참여할 수도 있고, 별도의 트랜잭션으로 진행할 수도 있고, 에러를 발생시키는 등 여러 선택을 할 수 있다. 이렇게 하나의 트랜잭션이 다른 트랜잭션을 만나는 상황을 그림으로 나타내면 다음과 같이 나타낼수 있다.

트랜잭션은 데이터베이스에서 제공하는 기술이므로 커넥션 객체를 통해 처리한다. 그래서 1개의 트랜잭션을 사용한다는 것은 하나의 커넥션 객체를 사용한다는 의미를 가진다.
실제 데이터베이스의 트랜잭션을 사용한다는 점에서 물리 트랜잭션이라고도 한다. 물리 트랜잭션은 실제 커넥션에 롤백/커밋을 호출하는 것이므로 해당 트랜잭션이 끝나는 것이다.
spring에서는 실제 데이터베이스에서 처리하는 트랜젝션과 스프링에서 처리하는 트랜젝션을 구분지었는데 이것을 논리 트랜잭션이라고 한다.

외부 트랜잭션과 내부 트랜잭션이 1개의 물리 트랜잭션(커넥션)을 사용하는 경우
논리 트랜잭션개념이 도입된 덕분에 2개 이상의 트랜잭션을 다루는 경우에 대해 이해가 상당히 쉬워졌다.
spring의 @Transactional 어노테이션을 사용한다면 전파 속성을 지정할 수 있다, 실제로 @Transactional 어노테이션 인터페이스를 보면 이렇다.

(하단에 내려가 보면 propagation을 설정하는 부분을 볼 수 있다.)
트랜젝션을 적용한 예시를 보면 이렇게 작성할 수 있다.
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.stereotype.Service;
@Service
public class memberService {
@Transactional(propagation = Propagation.REQUIRED)
public void test(){
}
}
코드를 보면 REQUIRED를 볼 수 있는데 REQUIRED는 전파속성중 하나입니다.
REQUIRED를 포함한 7개의 전파 속성을 보면 다음과 같이 작성할 수 있다.
| 의미 | 기존 트랜잭션이 없는경우 | 기존 트랜잭션이 있는경우 | |
|---|---|---|---|
| REQUIRED | 트랜잭션이 필요하다 (없으면 새로 생성) | 새로운 트랜잭션을 생성한다 | 기존 트랜잭션에 참여 |
| REQUIRES_NEW | 항상 새로운 트랜잭션이 필요하다 | 새로운 트랜잭션을 생성한다 | 기존의 트랜잭션을 보류시키고 새로운 트랜잭션을 생성 |
| SUPPORTS | 트랜잭션이 있으면 지원한다 (없어도 된다) | 트랜잭션 없이 진행한다 | 기존 트랜잭션에 참여 |
| NOT_SUPPORTED | 트랜잭션을 지원하지 않는다 (트랜잭션 없이 진행) | 트랜잭션 없이 진행한다 | 기존의 트랜잭션을 보류시키고 트랜잭션 없이 진행 |
| MANDATORY | 트랜잭션이 의무이다 (반드시 필요하다) | IllegalTransactionStateException 예외발생 | 기존 트랜잭션에 참여 |
| NEVER | 트랜잭션을 지원하지 않는다 (기존 트랜잭션도 허용하지 않는다.) | 트랜잭션 없이 진행한다 | IllegalTransactionStateException 예외발생 |
| NESTED | 중첩(자식) 트랜잭션을 만든다 | 새로운 트랜잭션을 생성한다 | 중첩 트랜잭션을 만든다 |
https://kdhyo98.tistory.com/31
https://kafcamus.tistory.com/30