트랜잭션
AOP를 이용해 트랜잭션을 이해하고 적용해볼 수 있습니다.
트랜잭션은 2개 이상의 쿼리문을 함께 실행하는 프로그래밍 개념입니다.
트랜잭션에서 함께 실행되는 쿼리문들은 모두 함께 성공하거나
실패해야 합니다.
위 표의 4가지 원칙에 따라 기능을 묶으면 트랜잭션을 잘 사용할 수 있습니다.
root- context 내부에 transactionManager를 bean을 생성하고
의존성 주입을 했습니다.
namespace에서 필요한 이름에 체크를 해줍니다.
그럼 이제 트랜잭션을 시험해볼 두 개의 테이블을 만듭니다.
두 테이블의 컬럼 길이가 달라서 5 문자 이상의 insert문을
실행시켜 서로 충돌이 나도록 해보겠습니다.
트랜잭션이 필요할 때 -> 예시
다음과 같이 Sample1Mapper 와 Sample2Mapper를 생성하고
service를 생성합니다.
mapper xml은 귀찮으니까 따로 작성하지 않고 어노테이션으로
구문을 작성해보겠습니다.
// Sample1Mapper
package com.ict.mapper;
import org.apache.ibatis.annotations.Insert;
public interface Sample1Mapper {
@Insert("insert into tbl_test1 (col1) values (#{data})")
public int insertCol1(String data);
}
// Sample2Mapper
package com.ict.mapper;
import org.apache.ibatis.annotations.Insert;
public interface Sample2Mapper {
@Insert("insert into tbl_test2 (col2) values (#{data})")
public int insertCol2(String data);
}
아래는 service입니다.
// SampleTxService
package com.ict.service;
public interface SampleTxService {
public void addData(String value);
}
package com.ict.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.ict.mapper.Sample1Mapper;
import com.ict.mapper.Sample2Mapper;
import lombok.extern.log4j.Log4j;
@Log4j
@Service
public class SampleTxServiceImpl implements SampleTxService{
@Autowired
private Sample1Mapper mapper1;
@Autowired
private Sample2Mapper mapper2;
@Override
@Transactional
public void addData(String value) {
log.info("mapper1..........");
mapper1.insertCol1(value);
log.info("mapper2.........");
mapper2.insertCol2(value);
}
}
바로 위의 SampleTxServiceImpl을 이용해서
addData 메서드를 실행시켜 테스트 1번 테이블에는 값이 들어갈 수 있지만
2번 테이블에는 컬럼 문자 길이가 초과되어 들어가지 못하게 해보았습니다.
@Transactional 어노테이션을 걸어 두 개의 쿼리문을 묶었습니다.
이제 JUnit 테스트를 실행해보아야겠습니다.
알다시피 넣으려는 값이 5글자 이상으로 너무 커서
test_tbl2에는 들어가지 못하고 실패합니다.
원래 이럴 경우에 test_tbl1에는 위의 값이 들어가고
test_tbl2에는 값이 들어가지 못한 채 요청이 끝나게 되었지만
이제는 다릅니다.
두번째 pstmt가 실패했기 때문에 첫번째 pstmt가
.close()로 닫히고 return되는 것을 확인할 수 있습니다.
트랜잭션이 걸려있기 때문에 어느 한쪽에서 에러가 생기면
다른 쿼리문도 실행이 되지 않도록 설정이 된 것 입니다.
이를 이용해서 이제 여러 쿼리문을 복합적으로 처리하면서도
치명적인 DB에러를 피할 수 있게 되었습니다.