시니어 개발자가 초기 설정 한 프로젝트 소스를 체크아웃 받아 API 개발 중 트랜잭션 롤백 관련 삽질한 경험이다.
코드를 보니 아래와 같이 공통에서 AOP를 통해 트랜잭션을 자동으로 관리하도록 설정이 되어 있었다.
원인은 정말 허무했지만 나중의 삽질을 미연에 방지도록 기록한다.(원래 뭐든 알고나면 쉽지 않은가 😎)
TransactionConfig
package kr.test.portal.config.spring;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.interceptor.DefaultTransactionAttribute;
import org.springframework.transaction.interceptor.RollbackRuleAttribute;
import org.springframework.transaction.interceptor.RuleBasedTransactionAttribute;
import org.springframework.transaction.interceptor.TransactionInterceptor;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
@Slf4j
@Aspect
@Configuration
@RequiredArgsConstructor
public class TransactionConfig {
private final PlatformTransactionManager txManager;
@Bean
public TransactionInterceptor txAdvice() {
TransactionInterceptor txAdvice = new TransactionInterceptor();
List<RollbackRuleAttribute> rollbackRules = new ArrayList<>();
rollbackRules.add(new RollbackRuleAttribute(Exception.class));
DefaultTransactionAttribute attribute = new RuleBasedTransactionAttribute(TransactionDefinition.PROPAGATION_REQUIRED, rollbackRules);
String transactionAttributesDefinition = attribute.toString();
Properties txAttributes = new Properties();
txAttributes.setProperty("select*", transactionAttributesDefinition);
txAttributes.setProperty("insert*", transactionAttributesDefinition);
txAttributes.setProperty("update*", transactionAttributesDefinition);
txAttributes.setProperty("delete*", transactionAttributesDefinition);
txAttributes.setProperty("create*", transactionAttributesDefinition);
txAttributes.setProperty("add*", transactionAttributesDefinition);
txAttributes.setProperty("modify*", transactionAttributesDefinition);
txAttributes.setProperty("remove*", transactionAttributesDefinition);
txAttributes.setProperty("useTransaction*", transactionAttributesDefinition);
txAttributes.setProperty("select*", transactionAttributesDefinition);
txAdvice.setTransactionAttributes(txAttributes);
txAdvice.setTransactionManager(txManager);
return txAdvice;
}
@Bean
public DefaultPointcutAdvisor txAdviceAdvisor() {
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression("execution(* kr.test.portal..impl.*Impl.*(..))");
return new DefaultPointcutAdvisor(pointcut, txAdvice());
}
}
1. 트랜잭션 인터셉터를 설정하여 롤백 규칙과 트랜잭션을 적용할 메서드명에 대한 규칙을 정의
2. 트랜잭션 인터셉터와 포인트컷을 연결하는 어드바이저를 생성하여 반환(포인트컷을 사용하여 트랜잭션을 적용할 대상 메서드 경로 설정)
이 두 개의 빈을 통해 AOP가 적용된 메서드가 실행될 때 자동으로 트랜잭션을 시작하며, 정상 처리 시 커밋되고, 예외 발생 시 롤백되도록 되어 있었다.
포인트컷의 경로에 Impl클래스를 만들고 비즈니스 로직을 만들며 테스트 하고 있었는데 예외가 발생해도 롤백이 되지 않았었다. 😥
원인은 바로 대상 메서드에서 발생한 예외를 밖으로 던져야 트랜잭션 인터셉터가 개입할 수 있는데 내 경우는 예외 발생 시 그냥 catch문에서 로그만 출력하고 끝냈었다.
어차피 해당 로직은 open API 호출해서 가져온 데이터를 DB에 저장만 하고 프론트 단에서 딱히 후처리하는게 없어그냥 try catch를 지우고 throws Exception으로 예외를 던진 뒤 정상적으로 롤백이 된 걸 확인 할 수 있었다.
개인 스터디 기록을 메모하는 공간이라 틀린점이 있을 수 있습니다.
틀린 점 있을 경우 댓글 부탁드립니다.
'IT > development' 카테고리의 다른 글
[java] 다형성을 이용한 중복 코드 분리 (feat. 정적 중첩 클래스) (36) | 2024.12.25 |
---|---|
[thymeleaf] Thymeleaf Layout (feat. sb-admin 2) (33) | 2024.12.22 |
[java] extends (feat. simple) (2) | 2024.10.23 |
[spring] spring security 초간단 예시 (3) | 2024.10.13 |
[java] Encapsulation(feat. simple example) (5) | 2024.09.29 |
댓글