Spring Framework에서 CUD에 Transaction에 대해 DB에 데이터를 저장하지 않고 기능이
정상적으로 동작하는지 확인이 필요한 경우가 있을 수 있다.
이 때 새로운 User Transaction을 정의한 후 모든 Transaction을 Rollback처리하도록 설정하면 가능하다.
본 기능에 대해서는 많은 테스트를 수행하지 않았지만, 하나의 테이블에 대한 Insert에 대해서는 정상적으로
동작하는것을 테스트하였다.
Transaction은 일반적으로 서비스 단위에서 시작하지만, 모든 Trasnsaction을 Rollback 처리하기 위한 User
Transaction을 생성을 어디에서 해야할지 정의해야한다.
본 예제에서는 User Transaction을 Interceptor에서 정의한 후 해당 Transaction을 Rollback only로 설정하였다.
예제 프로그램은 다음과 같다.
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionDefinition; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.DefaultTransactionDefinition; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; public class SimulatorInterceptor extends HandlerInterceptorAdapter implements InitializingBean { private static final Logger LOGGER = LoggerFactory.getLogger(SimulatorInterceptor.class); private boolean enabled; private boolean keyEnabled; private String key; private PlatformTransactionManager txManager; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String requestUri = ((HttpServletRequest)request).getRequestURI(); String keyValue = (String)request.getParameter(key); keyValue = keyValue != null ? keyValue : "N"; if (enabled && (keyEnabled && "Y".equalsIgnoreCase(keyValue))) { LOGGER.info("This [{}] request is for simulation", requestUri); DefaultTransactionDefinition transDef = new DefaultTransactionDefinition(); transDef.setName("SimulationTx"); transDef.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); transDef.setReadOnly(false); transDef.setTimeout(30); try { /** New transaction **/ TransactionStatus status = txManager.getTransaction(transDef); if (status.isNewTransaction()) { LOGGER.warn("This [{}] transaction is created", requestUri); } /** Set roll back only **/ status.setRollbackOnly(); LOGGER.warn("This [{}] request is roll back only", requestUri); } catch(Exception ex) { LOGGER.error(ex.getMessage()); } } return super.preHandle(request, response, handler); } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView mav) throws Exception { SimulatorContextHolder.rollback(); /** Do nothing **/ } public void setEnabled(boolean enabled) { this.enabled = enabled; } public void setKey(String key) { this.key = key; } public void setKeyEnabled(boolean keyEnabled) { this.keyEnabled = keyEnabled; } public void setTxManager(PlatformTransactionManager txManager) { this.txManager = txManager; } @Override public void afterPropertiesSet() throws Exception { if (keyEnabled && key == null) { this.key = "simulationYn"; } } } |
1. DefafultTransactionDefinition을 통해 Transaction 이름, Prapagatio, ReadOnly 및 Timeout을 정의한다.
2. TransactionManager를 통해 TransactionStatus를 생성한다.
3. TransactionStatus.setRollbackOnly를 통해 모든 Transaction을 Rollback처리한다.
본 예제에서는 Interceptor에서 User Transaction을 REQUIRED로 생성한 후 이후 모든 Transaction이 REQUIRED로
정의되어 있는 경우에 사용이 가능한다.
User Transaction 생성 이후 다음 Transaction이 REQUIRED_NEW로 정의되면 정상적으로 모든 Transaction이 Rollback 되지 않는다.
'Spring Framrwork' 카테고리의 다른 글
Spring Framwork의 RequetMapping 정보 추출하기 (0) | 2020.03.03 |
---|---|
Mybatis TypeHandler를 이용한 Password 암호화 (0) | 2020.03.03 |
Mybatis SQL Logging (0) | 2019.04.28 |
Spring Framework Custom Annotation 만들기 (0) | 2018.09.12 |
Spring Batch Step간 데이터 공유 (0) | 2018.09.05 |