해결된 질문
작성
·
41
·
수정됨
0
@SpringBootTest
class MemberServiceTest {
@Autoworied lateinit var memberService: MembersService
@Test
fun get() {
memberService.get(1L)
}
}
@Service
class MemberService(
private val txManager: PlatformTransactionManager,
) {
@Transactional(readOnly = true)
fun get(id: Long) {
val tx = txManager.getTransaction(DefaultTransactionAttribute())
println("isCurrentTransactionReadOnly()=${TransactionSynchronizationManager.isCurrentTransactionReadOnly()}")
println("isActualTransactionActive()=${TransactionSynchronizationManager.isActualTransactionActive()}")
println("isNewTransaction()=${tx.isNewTransaction()}")
// get
}
}
제가 기대한건
isNewTransaction = true
인데요 -> 가장 처음 호출된 @Transactional이 있는 service 메서드이기 때문에
그런데
테스트 코드로 실행해도 그렇고, API로 get 메서드가 호출되도록 해봐도 그렇고
모두 isNewTransaction = false
로 나옵니다.
내부 트랜잭션이 아니라 외부 트랜잭션이라고 생각했는데 왜 false일까요....
09:54:40.059 [Test worker] DEBUG o.s.o.j.JpaTransactionManager - Creating new transaction with name [com.application.service.member.MemberService.get]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly
09:54:40.062 [Test worker] DEBUG o.s.o.j.JpaTransactionManager - Opened new EntityManager [SessionImpl(16208286<open>)] for JPA transaction
09:54:40.075 [Test worker] DEBUG o.h.e.t.i.TransactionImpl - On TransactionImpl creation, JpaCompliance#isJpaTransactionComplianceEnabled == false
09:54:40.075 [Test worker] DEBUG o.h.e.t.i.TransactionImpl - begin
09:54:40.081 [Test worker] DEBUG o.s.o.j.JpaTransactionManager - Exposing JPA transaction as JDBC [org.springframework.orm.jpa.member.HibernateJpaDialect$HibernateConnectionHandle@486e4af6]
09:54:40.083 [Test worker] TRACE o.s.t.i.TransactionInterceptor - Getting transaction for [com.application.service.member.MemberService.get]
09:54:40.084 [Test worker] DEBUG o.s.o.j.JpaTransactionManager - Found thread-bound EntityManager [SessionImpl(16208286<open>)] for JPA transaction
09:54:40.084 [Test worker] DEBUG o.s.o.j.JpaTransactionManager - Participating in existing transaction
TransactionSynchronizationManager.isCurrentTransactionReadOnly()=true
TransactionSynchronizationManager.isActualTransactionActive()=true
outer.isNewTransaction()=false
Creating new transaction with name
이 나오는데
09:54:40.084 [Test worker] DEBUG o.s.o.j.JpaTransactionManager - Participating in existing transaction
이 로그도 나옵니다,,
답변 2
0
0
안녕하세요, 인프런 AI 인턴입니다. 또또록님.
스프링에서의 트랜잭션 전파와 관련하여 질문해 주신 내용에 대해 설명드리겠습니다.
@Transactional
을 통해 메서드를 감쌀 때, 스프링은 해당 메서드가 실행될 때마다 새로운 트랜잭션을 시작하지 않습니다. 기본적으로 스프링의 트랜잭션 전파는 PROPAGATION_REQUIRED
로 설정되어 있습니다. 이는 이미 실행 중인 트랜잭션이 있으면 현재 트랜잭션에 참여하고, 없으면 새 트랜잭션을 시작하는 동작입니다.
따라서, memberService.get(1L)
메서드가 @Transactional(readOnly = true)
로 정의되어 있었을 때, 스프링은 트랜잭션이 이미 존재한다고 판단하여 현재 트랜잭션을 사용하게 됩니다. txManager.getTransaction(DefaultTransactionAttribute())
로부터 가져온 트랜잭션 객체는 이미 존재하는 트랜잭션에 참여하게 되며, 이는 isNewTransaction()
이 false
로 나타나는 이유입니다.
테스트 환경이나 API 호출에서 동일한 현상이 발생하는 것은 테스트 또는 웹 요청 컨텍스트에서 이미 트랜잭션이 시작되어 있기 때문일 가능성이 높습니다.
관련해서 더 깊이 있는 자료를 원하신다면, 아래의 내용을 참고할 수 있습니다:
추가적인 질문이 있으시다면 언제든지 남겨주세요. 지식공유자께서도 곧 답변해 주실 것입니다. 😊
저는 질문자님의 이해를 돕고자 지식공유자의 기존 답변을 참고하여 유사한 답변 링크를 추천해드립니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.