인프런 커뮤니티 질문&답변

김승현님의 프로필 이미지
김승현

작성한 질문수

스프링 DB 2편 - 데이터 접근 활용 기술

spring webflux 와 spring data jpa Transaction 사용 시 문제

작성

·

812

0

토이프로젝트를 하다 어쩌다 보니 spring webflux를 사용하게 되고 spring data jpa 는 reactive 환경에서 사용하지 못한다는 것을 모른 채 개발하다가...

@SpringBootTest 에서 @Transactional 을 쓴 테스트에서 롤백이 되지 않는 현상을 발견했습니다..

 

 

TRACE 로 설정해 두고 실행시켜본 결과...```2024-01-11T00:54:00.058+09:00  INFO 18764 --- [    Test worker] c.s.o.s.StockMarketDataServiceTest       : Started StockMarketDataServiceTest in 10.371 seconds (process running for 11.483)
2024-01-11T00:54:00.124+09:00 DEBUG 18764 --- [    Test worker] o.s.orm.jpa.JpaTransactionManager        : Creating new transaction with name [com.stock.oppenheimer.service.StockMarketDataServiceTest.testAddByStockName]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
2024-01-11T00:54:00.125+09:00 DEBUG 18764 --- [    Test worker] o.s.orm.jpa.JpaTransactionManager        : Opened new EntityManager [SessionImpl(2129901484<open>)] for JPA transaction
2024-01-11T00:54:00.132+09:00 DEBUG 18764 --- [    Test worker] o.s.orm.jpa.JpaTransactionManager        : Exposing JPA transaction as JDBC [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@7b5f886d]
2024-01-11T00:54:00.606+09:00 DEBUG 18764 --- [    Test worker] o.s.orm.jpa.JpaTransactionManager        : Found thread-bound EntityManager [SessionImpl(2129901484<open>)] for JPA transaction
2024-01-11T00:54:00.606+09:00 DEBUG 18764 --- [    Test worker] o.s.orm.jpa.JpaTransactionManager        : Participating in existing transaction
2024-01-11T00:54:00.606+09:00 TRACE 18764 --- [    Test worker] o.s.t.i.TransactionInterceptor           : Getting transaction for [com.stock.oppenheimer.service.StockMarketFacadeService.addStockMarketData]
2024-01-11T00:54:00.607+09:00 DEBUG 18764 --- [    Test worker] o.s.orm.jpa.JpaTransactionManager        : Found thread-bound EntityManager [SessionImpl(2129901484<open>)] for JPA transaction
2024-01-11T00:54:00.607+09:00 DEBUG 18764 --- [    Test worker] o.s.orm.jpa.JpaTransactionManager        : Participating in existing transaction
2024-01-11T00:54:00.607+09:00 TRACE 18764 --- [    Test worker] o.s.t.i.TransactionInterceptor           : Getting transaction for [com.stock.oppenheimer.service.StockDataService.addStockData]
2024-01-11T00:54:00.628+09:00 TRACE 18764 --- [    Test worker] o.s.t.i.TransactionInterceptor           : Completing transaction for [com.stock.oppenheimer.service.StockDataService.addStockData]
2024-01-11T00:54:00.629+09:00 TRACE 18764 --- [    Test worker] o.s.t.i.TransactionInterceptor           : Completing transaction for [com.stock.oppenheimer.service.StockMarketFacadeService.addStockMarketData]
2024-01-11T00:54:02.705+09:00 DEBUG 18764 --- [ctor-http-nio-2] o.s.orm.jpa.JpaTransactionManager        : Creating new transaction with name [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
2024-01-11T00:54:02.706+09:00 DEBUG 18764 --- [ctor-http-nio-2] o.s.orm.jpa.JpaTransactionManager        : Opened new EntityManager [SessionImpl(576234319<open>)] for JPA transaction
2024-01-11T00:54:02.706+09:00 DEBUG 18764 --- [ctor-http-nio-2] o.s.orm.jpa.JpaTransactionManager        : Exposing JPA transaction as JDBC [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@183cb66b]
2024-01-11T00:54:02.706+09:00 TRACE 18764 --- [ctor-http-nio-2] o.s.t.i.TransactionInterceptor           : Getting transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
2024-01-11T00:54:02.749+09:00 TRACE 18764 --- [ctor-http-nio-2] o.s.t.i.TransactionInterceptor           : Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
2024-01-11T00:54:02.749+09:00 DEBUG 18764 --- [ctor-http-nio-2] o.s.orm.jpa.JpaTransactionManager        : Initiating transaction commit
2024-01-11T00:54:02.749+09:00 DEBUG 18764 --- [ctor-http-nio-2] o.s.orm.jpa.JpaTransactionManager        : Committing JPA transaction on EntityManager [SessionImpl(576234319<open>)]
2024-01-11T00:54:02.758+09:00 DEBUG 18764 --- [ctor-http-nio-2] o.s.orm.jpa.JpaTransactionManager        : Closing JPA EntityManager [SessionImpl(576234319<open>)] after transaction
2024-01-11T00:54:02.759+09:00 DEBUG 18764 --- [ctor-http-nio-2] o.s.orm.jpa.JpaTransactionManager        : Creating new transaction with name [com.stock.oppenheimer.service.MarketDataService.fetchMarketData]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
2024-01-11T00:54:02.759+09:00 DEBUG 18764 --- [ctor-http-nio-2] o.s.orm.jpa.JpaTransactionManager        : Opened new EntityManager [SessionImpl(222446599<open>)] for JPA transaction
2024-01-11T00:54:02.759+09:00 DEBUG 18764 --- [ctor-http-nio-2] o.s.orm.jpa.JpaTransactionManager        : Exposing JPA transaction as JDBC [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@7a4f5e33]
2024-01-11T00:54:02.759+09:00 TRACE 18764 --- [ctor-http-nio-2] o.s.t.i.TransactionInterceptor           : Getting transaction for [com.stock.oppenheimer.service.MarketDataService.fetchMarketData]
2024-01-11T00:54:02.760+09:00 TRACE 18764 --- [ctor-http-nio-2] o.s.t.i.TransactionInterceptor           : Completing transaction for [com.stock.oppenheimer.service.MarketDataService.fetchMarketData]
2024-01-11T00:54:02.761+09:00 DEBUG 18764 --- [ctor-http-nio-2] o.s.orm.jpa.JpaTransactionManager        : Initiating transaction commit
2024-01-11T00:54:02.761+09:00 DEBUG 18764 --- [ctor-http-nio-2] o.s.orm.jpa.JpaTransactionManager        : Committing JPA transaction on EntityManager [SessionImpl(222446599<open>)]
2024-01-11T00:54:02.761+09:00 DEBUG 18764 --- [ctor-http-nio-2] o.s.orm.jpa.JpaTransactionManager        : Closing JPA EntityManager [SessionImpl(222446599<open>)] after transaction
2024-01-11T00:54:03.536+09:00 DEBUG 18764 --- [ctor-http-nio-2] o.s.orm.jpa.JpaTransactionManager        : Creating new transaction with name [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
2024-01-11T00:54:03.537+09:00 DEBUG 18764 --- [ctor-http-nio-2] o.s.orm.jpa.JpaTransactionManager        : Opened new EntityManager [SessionImpl(1744980953<open>)] for JPA transaction
2024-01-11T00:54:03.537+09:00 DEBUG 18764 --- [ctor-http-nio-2] o.s.orm.jpa.JpaTransactionManager        : Exposing JPA transaction as JDBC [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@364f6c3d]
2024-01-11T00:54:03.537+09:00 TRACE 18764 --- [ctor-http-nio-2] o.s.t.i.TransactionInterceptor           : Getting transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
2024-01-11T00:54:03.546+09:00 TRACE 18764 --- [ctor-http-nio-2] o.s.t.i.TransactionInterceptor           : Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
2024-01-11T00:54:03.546+09:00 DEBUG 18764 --- [ctor-http-nio-2] o.s.orm.jpa.JpaTransactionManager        : Initiating transaction commit

```

이러한 상황을 경험하게 되었습니다.

2024-01-11T00:54:02.706+09:00 DEBUG 18764 --- [ctor-http-nio-2] o.s.orm.jpa.JpaTransactionManager        : Opened new EntityManager [SessionImpl(576234319<open>)] for JPA transaction
2024-01-11T00:54:02.759+09:00 DEBUG 18764 --- [ctor-http-nio-2] o.s.orm.jpa.JpaTransactionManager        : Opened new EntityManager [SessionImpl(222446599<open>)] for JPA transaction
2024-01-11T00:54:03.537+09:00 DEBUG 18764 --- [ctor-http-nio-2] o.s.orm.jpa.JpaTransactionManager        : Opened new EntityManager [SessionImpl(1744980953<open>)] for JPA transaction

기존에 쓰이던 엔티티매니저가 없어지고 계속 새로운 엔티티 매니저가 오픈이 되고 있었습니다.

 

2024-01-11T02:01:18.229+09:00 DEBUG 25524 --- [    Test worker] o.s.orm.jpa.JpaTransactionManager        : Rolling back JPA transaction on EntityManager [SessionImpl(1495319789<open>)]

하지만 마지막에 롤백 되는 엔티티메니저는 [Test worker thread] 에서 소환한 엔티티매니저 단 하나였습니다.

 

해당 부분을 소환하는 코드는 이렇습니다..

 

@Transactional
public Flux<MarketData> saveMarketData(MktDataDTO marketDataDTO, StockData savedStockData) {
    MarketData marketData = conversionService.convert(marketDataDTO, MarketData.class);
    marketData.setStockData(savedStockData);
    marketDataRepository.save(marketData);
    return Flux.just(marketData);
}

 

골이 당겨 오네요 ㅜㅜㅜ..

r2dbc 로 마이그레이션을 하지 않고 transaction 설정을 잘 이용해서 이 상황을 해결할 방법이 있을지 한번 여쭤봅니다.

코드 전문은

kimseunghyun-kr/oppenheimer at VolumeProfile (github.com)
여기 있습니다..

답변 2

0

spring webflux는 reactor 구현체로 동작하는 non-blocking 웹어플리케이션 프레임웍인데요. spring data jpa하고 호환이 잘 안되는 것으로 알고 있습니다.

 

특히 webflux 환경에서 ReactiveCrudRepository가 아닌 JpaRepository 사용하는 경우 데이터 처리하는 과정에서 의도치 않은 방식으로 처리 될 수 있어서 주의가 필요합니다.

 

spring webflux, jpa 관련 자료 찾아보시면 바로 아실 수 있으실 거라 생각합니다.

0

김영한님의 프로필 이미지
김영한
지식공유자

안녕하세요. 승현님

이 부분은 저도 잘 모르겠습니다.

혹시 아시는 분 있으면 도움 부탁드려요.

감사합니다.

김승현님의 프로필 이미지
김승현
질문자

추가적으로 spring data jpa 랑 spring data r2dbc 이용해서 같은 데이터소스에 다른 드라이버 연결을 할려고 하는데 이러면 아예 그냥 jdbc 커넥션이 없다고 나오네요

김승현님의 프로필 이미지
김승현

작성한 질문수

질문하기