Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
Tags
- 필드 주입
- cache
- KEVISS
- static
- Spring
- jpa
- VUE
- equals
- 생성자 주입
- hashcode
- Test
- 재정의
- 인덱스
- stream
- java
- 바이너리 카운팅
- docker
- lambda
- DDL
- SQL
- AOP
- jwt
- redis
- 조합
- MSA
- DI
- 테스트 코드
- select_type
- 열 속성
- StringBuilder
Archives
- Today
- Total
백엔드 개발자 블로그
@Transactional 본문
@Transactional에 대해서 알아보자
@Transactional이란?
- 스프링에서 트랜잭션 처리할 때 사용하는 어노테이션이다.
- 클래스, 인터페이스, 메소드에 사용할 수 있다.
작동순서
- 프록시 객체 생성
- PlatformTransactionManager를 사용하여 트랜잭션을 시작
- 메소드 실행
- 결과에 따라 Commit 또는 Rollback
Commit과 Rollback 발생하는 경우
- CheckedException or 예외가 없을 때는 Commit
- UncheckedException이 발생하면 Rollback
우선순위
- 클래스 메소드
- 클래스
- 인터페이스 메소드
- 인터페이스
설정
@Transactional 설정
속성 | 타입 | 설명 |
---|---|---|
value | String | 사용할 트랜잭션 관리자 |
propagation | enum: Propagation | 선택적 전파 설정 |
isolation | enum: Isolation | 선택적 격리 수준 |
readOnly | boolean | 읽기/쓰기 vs 읽기 전용 트랜잭션 |
timeout | int (초) | 트랜잭션 타임 아웃 |
rollbackFor | Throwable 로부터 얻을 수 있는 Class 객체 배열 | 롤백이 수행되어야 하는, 선택적인 예외 클래스의 배열 |
rollbackForClassName | Throwable 로부터 얻을 수 있는 클래스 이름 배열 | 롤백이 수행되어야 하는, 선택적인 예외 클래스 이름의 배열 |
noRollbackFor | Throwable 로부터 얻을 수 있는 Class 객체 배열 | 롤백이 수행되지 않아야 하는, 선택적인 예외 클래스의 배열 |
noRollbackForClassName | Throwable 로부터 얻을 수 있는 클래스 이름 배열 | 롤백이 수행되지 않아야 하는, 선택적인 예외 클래스 이름의 배열 |
주의사항
1. 인터페이스가 없는 경우
- @Transactional 어노테이션은 Spring AOP를 이용한다. 즉, Dynamic Proxy를 이용한다.Dynamic Proxy는 인터페이스 기반으로 동작하기 때문에 인터페이스가 없을경우 트랜잭션이 동작하지 않는다.
- 인터페이스 없이 트랜잭션 동작하게 하려면 CGLib(Code Generation Library) Proxy를 이용하면 된다.CGLib Proxy는 클래스에 대한 Proxy가 가능하기 때문에 인터페이스가 없어도 된다.
2. @Transactional은 public method에만 적용된다.
- @Transactional은 프록시 기반으로 동작하기 때문에 public method가 아니면 동작하지 않는다.
- 만약 private 에 @Transactional을 적용한다고 하면 IDE에서 컴파일 오류가 발생한다.
3. 동일한 클래스 내의 메소드 호출은 @Transactional이 동작하지 않는다.
클래스내의 한 메소드에서 @Transactional가 적용된 다른 메소드를 호출하면 @Transactional이 동작하지 않는다. 프록시로 접근하지 않고 직접 접근하기 때문이다.
@Controller
class PackingController {
packingService.packing();
}
@Service
class PackingService {
// 트랜잭션 선언되어있지 않음.
public void packing() {
...
callExternalApi();
processCompleted();
}
@Transactional
public void callExternalApi() {
...
}
@Transactional(propagation=Propagation.REQUIRES_NEW)
public void processCompleted() {
...
}
}
클래스 내 메소드를 호출하여 @Transactional을 동작하고 싶다면?
- 가장 간단한 방법은 새로운 클래스를 생성하여 메소드를 위임하는 것이다.
- 클래스 생성이 어렵다면 aspectj를 사용하면 된다.
@SpringBootApplication
@EnableTransactionManagement(proxyTargetClass = true, mode = AdviceMode.ASPECTJ)
@EnableLoadTimeWeaving(aspectjWeaving = EnableLoadTimeWeaving.AspectJWeaving.ENABLED)
public class AspectjApplication {
public static void main(String[] args) {
SpringApplication.run(AspectjApplication.class, args);
}
}
참고
- https://ducmanhphan.github.io/2020-04-10-Introduction-to-transactions-in-Spring-data-jpa/
- https://imiyoungman.tistory.com/9
- https://goddaehee.tistory.com/167
- https://madnix.tistory.com/entry/Transactional-사용시-rollback이-안될-경우
- https://medium.com/chequer/spring-transactional-caching-그리고-aspectj-1편-transactional-17eca8c33bf
'Spring' 카테고리의 다른 글
Dispatcher Servlet (0) | 2024.05.17 |
---|---|
@Controlleradvice, @ExceptionHandler (0) | 2024.05.16 |
OSIV (0) | 2024.05.11 |
DB 트래픽 분산 (0) | 2024.05.11 |
Redisson trylock 내부로직 (0) | 2024.05.11 |