소개
게시글
질문&답변
2021.10.06
@Transaction 전파 관련 문의
답변해주셔서 감사드립니다! osiv를 참고하여 on/off 조건으로 다음과 같이 테스트 결과를 정리해보았습니다. 추가 질문은 맨 마지막에 작성하였습니다. @RequiredArgsConstructor @Component public class TestComponent { private final MemberRepository memberRepository ; private final EntityManager em ; @Transactional ( propagation = Propagation . REQUIRES_NEW ) public void capsule ( Long id ) { Member member2 = em . find ( Member . class , id ); System . out . println ( "member2 = " + member2); } } @GetMapping ( "/em/{id}" ) // @Transactional public void findMember5 ( @PathVariable ( "id" ) Long id ) { Member member1 = memberRepository . findById ( id ). get (); System . out . println ( "member1 : " + member1); testComponent . capsule ( id ); } requires_new 로 적용 > 1) osiv on( 영속상태 유지(단, 수정 불가능). 즉 트랜잭션 범위 외에서도 영속 상태 유지 o) 조건 1 : 외부 메서드에 @Transactional 유 -> 다른 member 조회 조건 2 : 외부 메서드에 @Transactional 무 -> 같은 member 조회 2) osiv off( 트랜잭션 종료 시 영속성 컨텍스트를 닫는다. 즉 트랜잭션 범위 밖에서는 영속상태 유지 x) 조건 3 : 외부 메서드에 @Transactional 유 -> 다른 member 조회 조건 4 : 외부 메서드에 @Transactional 무 -> 다른 member 조회 조건 1, 3의 경우 osiv on/off 여부에 상관 없이 외부에 @Transactional이 있기 때문에 컨트롤러 메서드 레벨에서 transaction이 시작되며, 내부의 requires_new가 잘 동작하여 각각 다른 member가 조회됩니다. 조건 2,4 의 경우 osiv on/off 여부에 따라 member 조회 결과에 차이를 보이게 됩니다. 조건 4(osiv off)는 외부 메서드 내의 " repository.findById" 부분이 끝나자마자 영속성이 사라지게 되므로, 내부 메서드의 transaction이 완벽하게 분리가 되어 원하는대로 동작함을 확인했습니다.(내부 @transactional을 default로 설정해도 동일하게 동작) 조건 2(osiv on)는 외부 메서드 내의 "repository.findById" 실행 이후에도 (조회용)영속상태가 외부 메서드 종료시점까지 유지되는 것으로 이해했습니다. 하지만 이러한 조건이 내부 메서드에 적용된 requires_new로 분리가 되지 않는 점이 이해가 잘 가지 않습니다.. ㅠ
- 1
- 5
- 525
질문&답변
2021.10.02
@Transaction 전파 관련 문의
네 답변 감사합니다! 말씀하신대로 진행해서 정리해봤는데 다음과 같은 결과가 나왔습니다. AOP를 처음 사용해본거라, 조금 헷갈리는 부분이 있어서요~ㅠ 추가 질문 2가지가 있습니다. 1) 앞서 질문의 내부에서 호출된 메서드 "capsule"을 별도 클래스(TestComponent)로 분리하였습니다. @RequiredArgsConstructor @Component public class TestComponent { private final MemberRepository memberRepository ; private final EntityManager em ; @Transactional ( propagation = Propagation . REQUIRES_NEW ) public void capsule ( Long id ) { Member member2 = em . find ( Member . class , id ); System . out . println ( "member2 = " + member2); } } 2.1) 호출하는 메서드에 @Transactional 적용 안함 Controller의 "findMember5" 메서드에서 member find를 진행하고, 1)의 "capsule"메서드를 호출하였습니다. 이 때 "findMember5" 메서드에 @Transactional은 적용하지 않았습니다. @GetMapping ( "/em/{id}" ) // @Transactional public void findMember5 ( @PathVariable ( "id" ) Long id ) { Member member1 = memberRepository . findById ( id ). get (); System . out . println ( "member1 : " + member1); testComponent . capsule ( id ); } 이 경우, 동일한 member가 호출되었습니다. 간단히 그림으로 보면 다음과 같습니다. (사진) 2.2) 호출하는 메서드에 @Transactional 적용(주석 제거) (사진) @Transactional을 외부에도 적용했을 경우에는 member1, member2가 다른 결과가 나왔습니다. 이 경우에는 내부 메서드의 @Transactional(REQUIRES_NEW)가 정상적으로 동작한 것으로 이해했습니다. 질문 1 : 외부 메서드의 @Transactional 적용 여부에 따라 위와 같은 결과가 나오는데, 이유를 설명해주실 수 있으실까요? 오히려 2.1)의 트랜잭션이 완벽하게 분리가 될 것으로 생각했습니다. 질문 2 : 다른 AOP의 경우에도 @Transacional의 case(내부 @Transactional에만 Requires_new 적용)와 마찬가지로 내부 어노테이션에 다른 기능(옵션)을 부여할 수 있나요?
- 1
- 5
- 525
고민있어요
2021.06.03 11:31
이후 진행사항 문의
- 0
- 1
- 110
질문&답변
2021.06.03
@MainDiscountPolicy 삭제시 오류
안녕하세요 영한님! 비슷한 것으로 궁금해서 추가 질문드립니다. 그럼 해당 에러는 AllBeanTest의 컨테이너 생성 과정 중 -> AutoAppConfig.class를 통해 Component Scan을 통한 OrderServiceImpl의 생성과정에 생기는 NoUniqueBeanDefinitionException이라고 이해하면 될까요?
- 0
- 2
- 256