오늘은 몰랐으면 내일은 알면 된다

2022-12-15 (2) 트랜잭션 처리 본문

Java/JAVA 개발자 양성과정

2022-12-15 (2) 트랜잭션 처리

마스터피쓰 2022. 12. 15. 10:47

참고) Oracle 의 Sequence는 미리 일련번호를(캐시값을) 20개씩 만들도록 되어있다.(기본값)

그러다 종료가 되어버리면 캐시값은 다 날아가게 된다.

이를 방지하기 위해서는 생성시 nocache라고 명시해주면 된다. (그러나 생성에 시간이 걸리게 됨)

create sequence order_seq nocache;

지금 현재는 order insert에 트랜잭션 처리가 되어있지 않기 때문에, 위의 값으로 주문을 하게 되면 order_info 테이블에는 값이 들어가지만 order_line 테이블에는 값이 들어가지 않게 된다.

그러나 될거면 둘다되고 안될거면 둘다 안돼야 하기때문에, 트랜잭션 처리가 들어가야한다.

메소드 선언부에 @Transactional 어노테이션을 붙여준다. 이 어노테이션의 구성 자체가 Advice 구조로 되어있다.

@Override
@Transactional
public void insert(OrderInfo info) throws AddException {
    SqlSession session = null;
    try {
        session = sqlSessionFactory.openSession();
        //트랜잭션 처리는 AOP활용하여 선언적 트랜잭션으로 변경

        //주문기본정보 추가
        insertInfo(session, info);
        //주문상세정보 추가
        insertLines(session, info.getLines());
    } catch(Exception e) {
        e.printStackTrace();
        throw new AddException("insert에 실패했습니다.");
    } finally {
        if(session != null) {
            session.close();
        }
    }
}

rollbackFor 속성을 사용해서 특정 예외가 발생했을 때 rollback되게 해보자. exception이 발생하지 않으면 commit되게 한다.

@Override
@Transactional(rollbackFor = AddException.class)
public void insert(OrderInfo info) throws AddException {

그리고 이 어노테이션을 사용하기 위해 ApplicationContext로 가서 클래스의 선언부에 @EnableTransactionManagement를 붙여준다. 해당 어노테이션은 xml 버전 설정파일의 <tx:annotation-driven>와 동일한 효과를 가진다.

@Configuration
@ComponentScan(basePackages = {"com.my.repository", "com.my.service"})
@MapperScan(basePackages = {"mybatis"})
@EnableTransactionManagement //<tx:annotation-driven>
public class MyApplicationContext {

그 다음 Transaction 관리자 빈을 등록해준다. 생성자의 매개변수로는 dataSource가 들어간다.

@Bean
public DataSourceTransactionManager txManager() {
    DataSourceTransactionManager txManager = new DataSourceTransactionManager(dataSource());
    return txManager;
}

속성을 하나 더 살펴보면 Propagation이라는 메소드가 있다.

트랜잭션이 없으면 만들고, 있으면 호출된 메소드에 계속 전파시켜서 사용하는 것이 Propagation.REQUIRED이다.

반면 호출된 메소드에서도 각각 새로운 트랜잭션을 만들어서 사용하는것이 Propagation.REQUIRES_NEW이다.

 

junit 단위테스트 내에서 Transactional 어노테이션을 붙이면 자동롤백된다.