Transaction Template

2020. 5. 7. 18:37Java/Spring

728x90

1. @Transactional의 한계

public class TransactionInvoker {

    private A1Dao a1dao;
    private A2Dao a2dao;

    public void setA1dao(A1Dao dao){
        this.a1dao = dao;
    }

    public void setA2dao(A2Dao dao){
        this.a2dao = dao;
    }

    // 외부에서 호출하는 method
    public void invoke() throws Exception{
        doInternalTransaction();
    }

    @Transactional
    public void doInternalTransaction() throws Exception{
        a1dao.insertA1();
        a2dao.insertA2();
    }
}

 위의 코드를 실행해보면 @Transactional을 통해 Transaction이 적용되지 않는 것을 확인할 수 있습니다. Transaction이 적용되지 않는 이유는 @Transactional은 Proxy 방식으로 동작하는데, Proxy는 클래스 외부에서 호출하는 경우에만 동작하기 때문입니다.
 그러면 invoke 메소드에 @Transactional을 설정할 수 있습니다. Spring Transaction은 method 시작 시점에 Connection 객체를 얻고 종료 시점에 반납합니다. 처리 시간이 긴 method의 경우에는 불필요하게 오랫동안 DB Connection을 점유하면서 DB Lock이 유지되는 시간이 길어지기 때문에 invoke 메소드에 설정해주지 않는 것이 좋습니다.

2. Transaction Template

 Transaction Template이란 개발자가 Transaction의 시작 및 종료 시점을 명시적으로 결정할 수 있도록 Spring에서 제공하는 방법입니다. 아래의 예제처럼 Transaction Template은 Spring으로부터 TransactionManager를 주입받고 Transaction 속성을 설정해 줍니다. 그리고 execute 메소드 내에서 로직을 실행합니다.

import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.TransactionStatus;

public class TransactionInvoker {

    private A1Dao a1dao;
    private A2Dao a2dao;
    private TransactionTemplate transactionTemplate;

    public void setA1dao(A1Dao dao){
        this.a1dao = dao;
    }

    public void setA2dao(A2Dao dao){
        this.a2dao = dao;
    }

    public void setTransactionManager(PlatformTransactionManager transactionManager){
        this.transactionTemplate = new TransactionTemplate(transactionManager);
        this.transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
    }

    public void invoke() throws Exception{
        doInternalTransaction();
    }

    private void doInternalTransaction() throws Exception{
        transactionTemplate.execute(new TransactionCallbackWithoutResult(){
            public void doInTransactionWithoutResult(TransactionStatus status){
                try{
                    a1dao.insertA1();
                    a2dao.insertA2();
                }
                catch(Exception e){
                    status.setRollbackOnly();
                }
                return;
            }
        });
    }
}
728x90

'Java > Spring' 카테고리의 다른 글

Spring Batch  (0) 2020.07.02
Spring Boot  (0) 2020.06.09
Spring Singleton  (0) 2020.05.01
@ExceptionHandler  (0) 2020.04.26
AOP  (0) 2020.04.18