Choi의 고유결계

[Spring] @Transactional 주의사항, Rollback이 안돼요 본문

Spring

[Spring] @Transactional 주의사항, Rollback이 안돼요

믿을수없는맛 2022. 3. 19. 13:55
반응형

내용

  • 예외(Exception)의 문제
  • 호출의 문제
  • 접근 제어자의 문제

예외(Exception)의 문제

 

@Transactional 어노테이션은 기본적으로 Checked Exception에 대해서는 롤백시키지 않도록 되어있다.

 

Checked Exception? 

자바에서 문법적으로 try/catch와 같이 반드시 처리를 해줘야하는 예외이다.

처리를 해주지 않을경우 컴파일이 되지 않는다.

 

EX) Exception, IOException, SQLException등 Exception을 상속 받는 클래스중 RuntimeException을 제외한 모든 예외 클래스

 

그래서 만약 아래와같이 thorws를 통해 상위로 넘기게 해놓고, 원래 의도대로라면 홍길동 저장 후 null을 파라미터로 인한 Exception 을 감지해 @Transactional이 홍길동의 저장 을 취소하고 롤백을 해줄것 같지만 ExceptionChecked Exception이기 때문에 롤백 되지 않는다.

@Transactional
public void memeberSave() throws Exception {
  ObjectMapper objectMapper = new ObjectMapper();
  Member member1 = new Member("홍길동");
  save(check(member));
  
  // 오류가 발생한다고 가정!!
  save(check(null));
}

public Member check(Member member) throws Exception {
  if(member == null){
		throw new Exception();
	}
    ...
}

만약 Exception을 인식시켜 의도된 대롤 작동하게 하려면 아래와 같이 사요하면 되지만, 썩 좋은 방법이라고 말하기는 어렵다. 

@Transactional(rollbackFor = {Exception.class})

 대신 Checked Exception 이 발생하면 더욱 구체적인 Unchecked Exception을 발생하는 것이 좋을 것 같다.


호출의 문제

@Transactional은 두가지 모드를 가지고 있다. Proxy Mode와 AspectJ Mode가 있는데 Proxy Mode가 Default로 설정되어있다.
  • Proxy Mode인 경우

@Transactional이 적용되지 않은 Public Method에서 @Transactional이 적용된 Public Method를 호출할 경우, 트랜잭션이 동작하지 않는다.

 

프록시 모드에서는 memebrSave에서 오류가 나도 @Transactional이 적용 되지 않은 memberSaveTest에서 호출 했기 때문에 홍길동의 내용이 저장된다.

public int memberSaveTest() {
	Member member1 = new Member("홍길동");
	memeberSave(member1);
}
	
	
@Transactional
public void memebrSave(Member member) throws Exception {
    save(check(member));
    // 오류가 발생한다고 가정!!
    save(check(null));
}

 

  • AspectJ Mode인 경우

 

 

Non-Public 메서드에 적용하고 싶으면 AspectJ Mode에서 사용할 수 있다.

 


접근제어자의 문제

public 메소드에 적용해야한다. Protected, Private 메소드에서 선언하면 에러가 발생하지는 않지만, 동작하지도 않는다.

참고

 

반응형
Comments