spring 트랜잭션 예외---Transaction rolled back because it has been marked as rollback-only

문제가 생기다


최근 재구성 전 동료의 코드가 재구성된 후 코드를 디버깅하는 과정에서 프로젝트에서 우리가 정의한 이상 오류 정보가 아닌 서비스 호출 이상 오류가 발생했기 때문에 업무 코드의 오류가 아니라 프레임워크 차원의 오류라고 의심했다.

문제 배열


로그 검색을 통해 구체적인 오류 정보는 Transaction rolled back because it has been marked as rollback-only로 사무와 관련된 오류가 분명합니다.또한 업무 논리에서 로그 응답 상황을 조사한 결과 업무가 마지막까지 정확하게 집행되었지만 마지막으로 사무를 제출할 때 오류가 발생한 것을 발견했다.스프링 사무를 시작하면 코드가 정확하게 실행될 때 스프링은 사무의 마지막 사무 제출을 합니다. 이것은 사무 제출 때의 오류입니다.

문제 분석


코드에 대한 조회를 통해 업무 논리에 사무 플러그인이 존재하는 상황을 발견하였다.이상 창고에 대한 자세한 조사를 통해 내부 업무가 일정한 장면에서 이상을 던졌지만 외부 업무는try-catch로 받아들인 것을 발견하였다.그래서 내부 사무가 이상한 상황에서 외부 사무는 계속 집행되었다.

원인 해석


spring이 업무를 시작할 때,propagation의 매개 변수를 수정하지 않으면, 기본값은propagation입니다.REQUIRED.즉, 사무가 없으면 새로운 사무를 시작하고, 이미 존재하는 사무가 있으면 이 사무에 가입한다.내부 업무가 이상한 경우 이런 전파 방식이라면 정상적으로 굴러가야 하지만spring지식은 내부 업무에 롤백의 표시를 한다.그래서 내부 업무에서 던진 이상이 외부try-------catch에 있을 때 외부 업무는 정상적으로 실행되지만 마지막에 제출할 때 내부 업무에 롤백이 표시되어 있는 것을 발견하여 Transaction rolled back because it has been marked as rollback-only라는 이상 메시지를 던집니다.

솔루션


원래 장면에서 내부 사무의 이상은 외부 사무에 포착되고 내부 사무는 롤백으로 표시되며 외부 사무는 제출되고 마지막 사무는 검사 제출 시 Transaction rolled back because it has been marked as rollback-only 이상을 던집니다.
@Transactional(rollbackFor = Exception.class)
public void methodA(){
	insert();
	System.out.println(1 / 0);
}

@Transactional(rollbackFor = Exception.class)
public void methodB(){
	try{
		methodA();
	}catch(Exception e){
		System.out.println("   ");
	}
}

두 가지 상황으로 나누어 이 이상을 해결할 수 있다

  • 만약에 우리가 내부 이상이 필요한 경우 전체 사무를 스크롤하면 내부 사무에서 던진 이상을 외부 사무의try----catch에 처리하고 새로운 이상을 던질 수 있다. 또는 외부 사무가try-catch를 통해 이 이상을 처리하지 않을 수도 있다.
  • 물론 내부 사무를 다시 사용하지 않고 이곳에서만 사용하면 내부 사무를 직접 제거하고 외부와 하나의 사무로 통합시켜도 이 문제를 해결할 수 있다.
  • @Transactional(rollbackFor = Exception.class)
    public void methodA(){
    	System.out.println(1 / 0);
    }
    
    @Transactional(rollbackFor = Exception.class)
    public void methodB(){
    	try{
    		insert();
    		methodA();
    	}catch(Exception e){
    		throw new Exception("    ")
    	}
    }
    
  • 내부 사무가 이상한 경우 내부 사무만 굴러다니며 내부 사무의 사무 전파 방식을 수정
  • @Transactional(rollbackFor = Exception.class)
    public void methodA(){
    	System.out.println(1 / 0);
    }
    
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public void methodB(){
    	try{
    		insert();
    		methodA();
    	}catch(Exception e){
    		System.out.println("   ");
    	}
    }
    

    좋은 웹페이지 즐겨찾기