본문 바로가기

개발 기록/Spring-boot

[Spring-boot] 다중 TransactionManager 멀티 트랜잭션 처리

반응형

mySQL를 사용할때 JPA를 활용하고 MongoDB는 starter-data-mongodb 라이브러리를 활용하여 데이터베이스를 처리하는 중에 항상 고민였던것이 다중 트랜잭션 처리였다.

 

나는 각각 서비스 및 기능에 따른 데이터베이스를 나누어 관리하는것을 선호하는 편이기에 회원과 서비스 데이터베이스가 각각 나뉘어져 있다. 그렇기 때문에 별도로 다중 datasource를 선언하고 트랜잭션을 각각 선언하여 사용하고 있다.

 

최근 개발하던 중 MongoDB 기반으로 회원 컬렉션과 서비스 관련 컬렉션을 동시에 처리하는 로직이 생겨서 트랜잭션을 어떻게 처리를 해야할지 고민 하던중에 스프링에서 지원하는 ChainedTransactionManager를 발견하였다.

 

ChainedTransactionManager는 여러 트랜잭션을 모아서 각각의 리포지토리를 호출할때 맞는 트랜잭션이 발동하는거 같았다. 연관된 컬렉션이 중간에서 문제가 발생했을 경우 각각의 트랜잭션에 해당하는 컬렉션들이 정상 롤백되는것을 확인 할수 있었다.

 

설정은 정말 간단했다. (예제 소스 기준으로 설정을 추가하였다.)

 

* 기존 github 예제 소스 : https://github.com/realwater20/multimongodb.git

 

GitHub - realwater20/multimongodb

Contribute to realwater20/multimongodb development by creating an account on GitHub.

github.com

 

* 트랜잭션 설정

 

// 기존 트랜잭션 설정1
@Primary
@Bean("primaryTransactionManager")
public MongoTransactionManager primaryTransactionManager() {
    return new MongoTransactionManager(new SimpleMongoClientDatabaseFactory(mongodb_uri1));
}

// 기존 트랜잭션 설정2
@Bean("secondaryTransactionManager")
public MongoTransactionManager secondaryTransactionManager() {
    return new MongoTransactionManager(new SimpleMongoClientDatabaseFactory(mongodb_uri2));
}

// 멀티 트랜잭션 추가 new
@Bean("multiTransactionManager")
public PlatformTransactionManager multiTransactionManager(@Qualifier("primaryTransactionManager") PlatformTransactionManager primaryTransactionManager,
                                                          @Qualifier("secondaryTransactionManager") PlatformTransactionManager secondaryTransactionManager) {
    return new ChainedTransactionManager(primaryTransactionManager, secondaryTransactionManager);
}

 

* 테스트 코드 확인

 

@Transactional(transactionManager = "multiTransactionManager")
@Test
void test() {
    // primaryTransactionManager로 처리
    Test1 test1 = Test1.builder().title("test1").build();
    test1Repository.save(test1);
    assertEquals("test1", test1Repository.findById(test1.getId()).get().getTitle());

    // secondaryTransactionManager로 처리
    Test2 test2 = Test2.builder().title("test2").build();
    test2Repository.save(test2);
    assertEquals("test2", test2Repository.findById(test2.getId()).get().getTitle());
}

 

테스트 정상 확인

 

아직 기존 JPA 트랜잭션에도 적용해보진 못했지만 동일하게 잘 적용될거라 생각이 든다.

 

 

반응형