반응형
1. private 메소드에 걸린 @Transactional
은 동작하지 않는다
@Service
@RequiredArgsConstructor
public class ApiService {
private final ApiRepository apiRepository;
@Transactional
private void method1() {
apiRepository.save();
}
}
- 이유
- 스프링 AOP가 프록시 패턴을 사용하기 때문
- 프록시 패턴을 쓰게 되면 외부에서 동적으로 프록시 객체를 사용하게 되는데 private 필드는 외부에서 프록시 객체를 생성할 수가 없기 때문에 AOP가 동작할수가 없다
- 참고 글
- Spring - private 메서드에 @Transactional이 적용될까?
2. 내부 호출된 @Transactional
이 걸린 메소드에서는 동작하지 않는다
@Service
@RequiredArgsConstructor
public class ApiService {
private final ApiRepository apiRepository;
public void method1() {
method2();
}
@Transactional
public void method2() {
apiRepository.save();
}
}
- 이유
- 1번과 원리 동일
- 해결 방법
- 상위 메소드에 어노테이션을 붙여주어 해결할 수 있다
@Service @RequiredArgsConstructor public class ApiService { private final ApiRepository apiRepository; @Transactional public void method1() { method2(); } public void method2() { apiRepository.save(); } }
- 상위 클래스에서 method1과 method2를 순차적으로 호출해서 해결할 수 있다
@Controller @RequiredArgsConstructor public class ApiController { private final ApiService apiService; @GetMapping("/") public void call() { apiService.method1(); apiService.method2(); } }
3. Checked 예외 발생 시 롤백되지 않는다
@Service
@RequiredArgsConstructor
public class ApiService {
private final ApiRepository apiRepository;
@Transactional
public void method1() throws IOException {
apiRepository.save();
// IOException이 일어날만한 코드
...
}
}
- rollbackFor 옵션을 쓰면 해결할 수 있다
@Service @RequiredArgsConstructor public class ApiService { private final ApiRepository apiRepository; @Transactional(rollBackFor={IOException.class}) public void method1() throws IOException { apiRepository.save(); // IOException이 일어날만한 코드 ... } }
- Uncheked 예외로 다시 던져서 해결할 수도 있다
@Service @RequiredArgsConstructor public class ApiService { private final ApiRepository apiRepository; @Transactional public void method1() throws IOException { try { apiRepository.save(); // IOException이 일어날만한 코드 ... } catch(IOException e) { throw new RuntimeException(e); } } }
4. Unchecked 예외를 catch하더라도 롤백은 이루어진다
@Service
@RequiredArgsConstructor
public class ApiService {
private final ApiRepository apiRepository;
@Transactional
public void method1() {
try {
apiRepository.save();
// IOException이 일어날만한 코드
// ...
} catch (RuntimeException e) {
// ...
}
}
}
- noRollbackFor 옵션으로 해결할 수 있다
@Service
@RequiredArgsConstructor
public class ApiService {
private final ApiRepository apiRepository;
@Transactional(noRollbackFor={RuntimeException.class})
public void method1() {
try {
apiRepository.save(); // IOException이 일어날만한 코드
// ...
} catch (NullPointerException e) {
// ...
}
}
}
5. 전파 유형(Propagation)과 격리 수준(Isolation) 참고글
[Spring] @Transactional 어노테이션 이해하기(1) 전파유형(Propagation) 과 격리수준(Isolation)
반응형
'개발 > 스프링' 카테고리의 다른 글
[406 ERROR] Spring boot+ React 연동 시 발생하는 406 에러에 대해 (0) | 2021.09.17 |
---|