@Transactional 코드
public @interface Transactional {
String value() default "";
String transactionManager() default "";
Class<? extends Throwable>[] rollbackFor() default {};
Class<? extends Throwable>[] noRollbackFor() default {};
Propagation propagation() default Propagation.REQUIRED;
Isolation isolation() default Isolation.DEFAULT;
int timeout() default TransactionDefinition.TIMEOUT_DEFAULT;
boolean readOnly() default false;
String[] label() default {};
}
...
value(), transactionManager()
트랜잭션을 사용하려면 먼저 스프링 빈에 등록된 어떤 트랜잭션 매니저를 사용할지 알아야 한다.
코드로 직접 트랜잭션을 사용할 때 트랜잭션 매니저를 주입 받아서 사용했다.
@Transactional에서도 트랜잭션 프록시가 사용할 트랜잭션 매니저를 지정해주어야 한다.
사용할 트랜잭션 매니저를 지정할 때는 이 둘 중 하나에 트랜잭션 매니저의 스프링 빈의 이름을 적어주면 된다.
이를 생략하면 Default 값으로 기본으로 등록된 트랜잭션 매니저를 사용한다.
//예시
public class TxService {
@Transactional(value = "memberTxManager")
public void member() {...}
@Transactional(value = "orderTxManager")
public void order() {...}
//value = 생략가능
}
rollbackFor
예외 발생시 스프링의 기본 정책은
- 언체크 예외인 RuntimeException, Error와 그 하위 예외가 발생하면 롤백
- 체크 예외인 Exception과 그 하위 예외들은 커밋한다.
이 옵션을 사용하면 Exception이 발생해도 롤백하게 된다. (하위 예외 포함)
rollbackForClassName도 있는데 rollbackFor는 예외 클래스를 직접 지정하고, rollbackForClassName는 예외 이름을 문자로 넣으면 된다
@Transactional(rollbackFor = Exception.class)
noRollbackFor
rollbackFor와 반대, 기본 정책에 추가로 어떤 예외가 발생했을 때 롤백을 하지 않게 지정할 수 있다.
예외 이름을 문자로 넣을 수 있는 'noRollbackForClassName'도 존재한다.
propagation
트랜잭션 전파에 대한 옵션 추후 포스팅 예정
isolation
트랜잭션 격리 수준을 지정할 수 있다. 기본 값은 데이터베이스에서 설정한 트랜잭션 격리 수준을 사용하는 Default
대부분 데이터베이스에서 설정한 기준을 따르며, 개발자가 직접 격리 수준을 지정하는 경우는 드물다.
- DEFAULT : 데이터베이스에서 설정한 격리 수준
- READ_UNCOMMITTED : 커밋되지 않은 읽기
- READ_COMMITTED : 커밋된 읽기 (일반적인 수준)
- REPEATABLE_READ : 반복 가능한 읽기
- SERIALIZABLE : 직렬화 가능
timeout
트랜잭션 수행 시간에 대한 타임아웃을 초 단위로 지정한다. 기본 값은 트랜잭션 시스템의 타임아웃을 사용한다.
운영 환경에 따라 동작하는 경우도 있고 그렇지 않은 경우도 있기 때문에 꼭 확인하고 새양해야 한다.
timoutString도 있는데, 숫자 대신 문자 값으로 지정할 수 있다.
label
트랜잭션 애노테이션에 있는 값을 직접 읽어서 어떤 동작을 하고 싶을 때 사용한다. 일반적으로 사용하지 않는다.
readOnly
트랜잭션은 기본적으로 읽기, 쓰기가 가능한데 이 옵션의 값을 readonly - true 옵션을 사용하면 읽기 전용 트랜잭션이 생성된다. 이 경우 CUD가 안되고, R 기능만 작동한다.
(드라이버나 DB에 따라 정상작동하지 않는 경우도 있다.
이 옵션을 사용하면 다양한 성능 최적화가 발생할 수 있다.
readOnly옵션은 크게 3곳에서 사용된다.
- 프레임워크
- JdbcTemplate은 읽기 전용 트랜잭션 안에서 변경 기능을 사용하면 예외를 던진다.
- JPA는 읽기 전용 트랜잭션의 경우 커밋 시점에 플러시를 호출하지 않는다. 읽기 전용이니 변경에 사용되는 플러시를 호출할 필요가 없다. 추가로 변경 감지를 위한 스냅샷 객체도 생성하지 않는다. 이렇게 JPA에서는 다양한 최적화가 발생한다.
- JDBC 드라이버
- DB와 드라이버 버전에 따라서 다르게 작동되기 때문에 사전에 확인이 필요하다.
- 읽기 전용 트랜잭션에서 변경 쿼리가 발생하면 예외를 던진다.
- 읽기, 쓰기(마스터, 슬레이브) 데이터베이스를 구분해서 요청한다. 읽기 전용 트랜잭션의 경우 읽기(슬레이브) DB의 커넥션을 흭득해서 사용한다.
- 예) https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-source-replica-relication-connection.html
- 데이터베이스
- DB에 따라 읽기 전용 트랜잭션의 경우 읽기만 하면 되므로, 내부에서 성능 최적화가 발생한다.
출처 관련 : https://tan-sog.tistory.com/90
'Spring' 카테고리의 다른 글
[Spring] 스프링 트랜잭션 전파 기본 개념 (0) | 2024.08.22 |
---|---|
[Spring] 스프링 트랜잭션 - 4 (예외와 트랜잭션 커밋, 롤백) (0) | 2024.08.22 |
[Spring] 스프링 트랜잭션 - 2 (트랜잭션 AOP 주의 사항) (0) | 2024.08.21 |
[Spring] 스프링 트랜잭션 - 1 (트랜잭션 적용 확인) (0) | 2024.08.21 |
[Spring] 파일 업로드 (0) | 2024.07.09 |