Spring/Spring

[Spring][Data Access] 1-1. Transaction Manager: Advantages of the Spring Framework’s Transaction Support Model

noahkim_ 2024. 8. 11. 04:30

1. Global Transactions (Distributed Transactions)

  • 여러 트랜잭션 리소스를 하나의 트랜잭션으로 묶어 관리 (atomic)
  • 여러 자원간의 데이터 일관성 유지 O

 

JTA

  • Java Transaction API
  • Java에서 전역 트랜잭션을 관리하기 위한 표준 API

 

단점
  • 복잡성: 예외처리 모델
  • 의존성: JNDI를 통해 UserTransaction 객체 주입받아야 함
더보기
public class JTADemo {
    public static void main(String[] args) {
        UserTransaction userTransaction = null;
        try {
            // JNDI를 통해 UserTransaction 객체를 주입받아야 함
            InitialContext context = new InitialContext();
            userTransaction = (UserTransaction) context.lookup("java:comp/UserTransaction");
            
            // 트랜잭션 시작
            userTransaction.begin();

            // 비즈니스 로직 수행 (예: 여러 데이터베이스에 걸친 작업)
            performBusinessLogic();

            // 트랜잭션 커밋
            userTransaction.commit();

        } catch (Exception e) {
            // 예외 발생 시 트랜잭션 롤백
            try {
                if (userTransaction != null) {
                    userTransaction.rollback();
                }
            } catch (Exception rollbackEx) {
                System.out.println("Rollback failed: " + rollbackEx.getMessage());
            }
            System.out.println("Transaction failed: " + e.getMessage());
        }
    }

    private static void performBusinessLogic() throws Exception {
        // 예외를 던질 수 있는 비즈니스 로직
        System.out.println("Executing business logic...");
        // 예를 들어, 데이터베이스 작업 중 예외 발생 가능
        if (Math.random() > 0.5) {
            throw new Exception("Simulated business logic failure");
        }
        System.out.println("Business logic completed successfully.");
    }
}

 

EJB CMT

  • Enterprise JavaBeans Container Managed Transations
더보기
@Stateless
public class CMTExampleBean {

    // EJB CMT를 사용하여 선언적으로 트랜잭션을 관리
    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public void performTransaction() {
        // 비즈니스 로직 수행
        System.out.println("Performing business logic inside a container-managed transaction.");

        // 예외가 발생하면 컨테이너가 자동으로 트랜잭션을 롤백
        if (Math.random() > 0.5) {
            throw new RuntimeException("Simulated failure");
        }

        System.out.println("Business logic executed successfully.");
    }
}

 

장점
  • 선언적 트랜잭션 관리 (트랜잭션 관련 코드 작성 X)
  • 자동 트랜잭션 관리 (by 컨테이너)

 

단점
  • 의존성: JNDI에 의존적
  • 유연성 X: JTA에 강하게 결합 (컨테이너가 JTA를 통해 트랜잭션 관리)

 

2. Local Transactions

  • 특정 트랜잭션 리소스와 연관된 트랜잭션 (JDBC, FileSystem 등)
  • 단일 자원에 대해서만 트랜잭션 관리 수행

 

단점
  • Invasivenss (트랜잭션 관련 코드 작성 필수)
  • 다중 자원 간 트랜잭션 불가능 (JTA X)

 

3. Spring Framework’s Consistent Programming Model

  • Spring Framework는 전통적인 Java 트랜잭션 관리의 한계를 극복하고, 일관된 프로그래밍 모델을 제공

 

장점
  • 의존성 X (EJB): 독립적인 트랜잭션 관리자를 통해 전역 트랜잭션 관리 가능 (XML, Annotation)
  • 선언적 트랜잭션 관리: 설정을 통한 트랜잭션 관리 규칙 정의
  • 일관된 프로그래밍 모델: 로컬 트랜잭션과 전역 트랜잭션 간의 차이를 일관된 방식으로 처리 (트랜잭션 추상화)

 

더보기

설정

@Configuration
@EnableTransactionManagement
public class AppConfig {

    // JTA 트랜잭션 매니저 설정
    @Bean
    public PlatformTransactionManager transactionManager() {
        return new JtaTransactionManager();
    }

    // 트랜잭션 속성 설정
    @Bean
    public TransactionInterceptor transactionInterceptor(PlatformTransactionManager transactionManager) {
        Properties transactionAttributes = new Properties();

        // 모든 메서드에 대해 REQUIRED 속성을 적용
        transactionAttributes.setProperty("*", "PROPAGATION_REQUIRED");

        TransactionInterceptor transactionInterceptor = new TransactionInterceptor();
        transactionInterceptor.setTransactionManager(transactionManager);
        transactionInterceptor.setTransactionAttributes(transactionAttributes);

        return transactionInterceptor;
    }

    // 트랜잭션 어드바이스를 자동으로 적용할 Bean을 지정
    @Bean
    public BeanNameAutoProxyCreator transactionAutoProxy() {
        BeanNameAutoProxyCreator proxyCreator = new BeanNameAutoProxyCreator();
        proxyCreator.setInterceptorNames("transactionInterceptor");
        proxyCreator.setBeanNames("*Service");  // 예: 서비스 계층에 트랜잭션을 적용
        return proxyCreator;
    }
}

 

더보기

트랜잭션 사용 (선언적)

@Service
public class ExampleService {

    @Transactional // 이 메서드는 트랜잭션 내에서 실행됨
    public void executeInTransaction() {
        // 트랜잭션 내에서 실행될 비즈니스 로직
        System.out.println("Executing business logic within a transaction.");
    }
}

 

더보기

일관된 모델

@Service
public class TransactionalService {

    @Autowired
    private JdbcTemplate jdbcTemplate; // 로컬 트랜잭션 사용

    @Transactional
    public void performDatabaseOperation() {
        // 로컬 트랜잭션에 대한 작업 수행
        jdbcTemplate.update("INSERT INTO my_table (column1) VALUES (?)", "Value1");

        // 로컬 트랜잭션과 전역 트랜잭션 간의 코드 차이가 없음
        System.out.println("Database operation performed in a transaction.");
    }
}

 

출처