@Transactional(통과)

비동기 동기 및 트랜잭션 전파에 대해 자세히 알아보십시오…

옵션 설명

가능성 설명
필요한 기본 옵션
상위 트랜잭션이 있으면 조인하고, 그렇지 않으면 새 트랜잭션을 만듭니다.
중간에 있는 자식/부모에서 롤백이 발생하면 자식과 부모 모두 롤백됩니다.
REQUIRES_NEW 새 트랜잭션 생성
메서드 호출이 중첩되더라도 각 롤백이 수행됩니다.
필수적인 반드시 상위 트랜잭션에 참여하십시오.
상위 트랜잭션이 존재하지 않으면 예외가 발생합니다.
지원 즉, 메서드에 트랜잭션이 필요하지 않지만 진행 중인 트랜잭션이 있으면 이를 사용합니다. 진행 중인 트랜잭션이 없더라도 메서드는 정상적으로 작동합니다.
중첩됨 상위 트랜잭션이 존재하면 상위 트랜잭션 내에 중첩되고, 상위 트랜잭션이 존재하지 않으면 새로운 트랜잭션이 생성됩니다.
상위 트랜잭션에서 예외가 발생하면 하위 트랜잭션도 롤백됩니다.
하위 트랜잭션에서 예외가 발생하더라도 상위 트랜잭션은 롤백되지 않습니다. 이때 롤백은 부모 트랜잭션이 자식 트랜잭션을 호출하는 지점까지만 롤백한다. 그 후 상위 트랜잭션에 문제가 없으면 상위 트랜잭션이 커밋되어 완료됩니다.
현재 트랜잭션이 있는 경우 중첩된 트랜잭션 내에서 실행되고, 그렇지 않으면 REQUIRED처럼 동작합니다.
절대 메서드에는 트랜잭션이 필요하지 않습니다. 진행 중인 트랜잭션이 있으면 예외가 발생합니다.

위에.. 이렇게 정리를 해보는데 사실 위 두개 빼고는 써본적이 없어서… 필요할 때 찾아서 사용할 수 있을 것 같아요…?

필요한 -> 부모와 자식 트랜잭션이 진행되는 동안 자식에서 예외가 발생하면 부모가 성공하더라도 트랜잭션 전체가 실패한다.

REQUIRES_NEW -> 가장 이상한 점은… 무조건 새 트랜잭션을 열면 자식이든 부모든 아무 효과가 없어야 하는데 효과가 있습니다. 왜 …?

상위 트랜잭션이 트랜잭션을 호출하고 하위 트랜잭션이 그 안에 새로운 트랜잭션을 생성하더라도 대부분의 경우 하위 트랜잭션의 예외가 상위 트랜잭션으로 전파됩니다…

간단한 예를 들어

class 자식클래스{

private final TestRepository testRepository;

public void 자식클래스트랜잭션(){
	testRepository.test();
	throw new RunTimeException("자식클래스트랜잭션예외");
}

}




class 부모클래스{


private final 자식클래스 자식클래스;

private final TestRepository testRepository;


public void 부모클래스트랜잭션(){

	testRepository.test();
	자식클래스.자식클래스트랜잭션();
	

}


}

이 경우 예외가 전파되고 있음을 알 수 있습니다.

해결책은 상위 트랜잭션에서 예외를 포착하거나 해결하는 것입니다.

반대로 부모가 예외를 던지면 자식은 좋은 거래를 하게 됩니다.

필수적인-> 부모로부터 트랜잭션이 있으면 병합되고 부모로부터 트랜잭션이 없으면 예외가 발생합니다.


개발 과정에서 서비스 계층 영역의 메서드에 트랜잭션이 자주 병합되거나 중첩되는 경우가 있을 수 있습니다.

댓글을 작성할 때 + 알림을 보낸다고 가정해 보겠습니다.

댓글은 성공했지만 알림 전송은 실패했습니다… 모든 롤백이 발생하고 있습니다… 이 경우 어떻게 해야 합니까?

첫째, 별도의 스레드를 실행할 때 스레드 자체가 다르고 서로 영향을 주지 않도록 전혀 비동기적으로 적용합니다. (근데 꼭 async를 쓸 필요가 있을까? 알림을 보내는 데는 오래 걸리지 않으니 async 말고 sync 방식이 있는지 알아보자.)

1. 먼저 @async를 사용하여 부모 스레드와 자식 스레드가 영향을 받지 않도록 다르게 설정합니다.
-> 오류 발생 시 상위 트랜잭션도 실행되는가? 점검 해보자.
@transactionalListener 기본적으로 단계는 AFTER_COMMIT이므로 상위 트랜잭션이 커밋된 후에 실행됩니다.

@async + @transactionalListener
1. 상위 오류 -> 하위 트랜잭션을 전혀 실행할 수 없습니다.
2. 자식 오류 -> 부모 트랜잭션 실행 성공, 자식 트랜잭션 실행 오류

그러나 비동기식을 사용하여 트랜잭션을 분리하는 것이 맞습니까?


로그를 보면 비동기식이라 쓰레드가 다르니 세션이 다른거죠.
@transactionalListener를 삭제하자

@async + @EventListenr ->

상위 트랜잭션이 실패하더라도 하위 트랜잭션이 실행됩니다. -> 웃기다…? ㅋㅋㅋ..
모든 것을 별도로 실행하십시오.

@비동기 우리는 뺍니다
@Transactional+@TransactionalEventListener
1. 부모의 실수 -> 부모의 실수 자식의 실수
2. 자식 실패 -> 단, 부모가 커밋된 상태에서 실행이 되기 때문에 자식이 실패하더라도 부모는 영향을 받지 않는다.

위의 방법이 제가 원하는 방법인가요…?