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

emkemkemk님의 프로필 이미지
emkemkemk

작성한 질문수

자바 ORM 표준 JPA 프로그래밍 - 기본편

영속성 컨텍스트 2

@Transactional 에 따른 변경감지 작동여부 질문

해결된 질문

작성

·

831

·

수정됨

1

안녕하세요! 먼저 좋은 강의 감사하다는 말씀 드립니닷!

개인 프로젝트 수행 중에, 변경 감지와 관련한 이슈를 발견해서 질문드립니다.

물론 개인 프로젝트 관련한 질문은 안 받아주시는 것을 충분히 숙지하고 있지만, 개념적인(?) 내용이라 혹시 도움 받을 수 있을까 싶어 질문드립니다. (사실 아무리 생각해봐도 모르겠습니다..ㅠㅠ)

상황

  • 한 트랜잭션 안에서, 엔티티 객체를 만들고 이를 영속성 컨텍스트에 올려 id 값을 받아와 이 id 값을 가지고 해시값을 만들어 해당 해시값을 다시 엔티티 객체에 할당하려 합니다.

문제

문제는 위 작업을 수행하는 메소드의 @Transactional 위치에 따라 변경감지가 될 때가 있고 안 될 때가 있다는 점입니다.


위 쪽의 create(ShortUrlCreateRequest request) 메서드를 호출하여 아래에 오버로딩된 create(String originUrl, Period expirationPeriod) 를 통해 위에 서술한 작업을 하려합니다. (Repository 객체는 Data Jpa Repository를 사용하고 있습니다.)

create(ShortUrlCreateRequest request) 를 호출하면,
아래의 create(String originUrl, Period expirationPeriod) 메서드에 @Transactional 을 붙였음에도 아래와 같이 insert 문만 호출됩니다.


이번에는 위의 create()@Transactionl 붙였을 때 입니다.


insert 문과 update 문 모두 의도한 대로 호출되는 것을 확인할 수가 있습니다.

트랜잭션 진입 시점이 다른 것인데 왜 이에 따라 변경감지 가 일어나고/ 안 일어나는 지 감을 잡지 못하겠습니다. 일말의 힌트를 주실 수 있을까요?

항상 영한님과 서포터님들께 감사드립니닷!!

답변 1

3

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

안녕하세요. haero77님

스프링은 프록시 방식의 AOP로 동작합니다. 따라서 외부에서 메서드 호출이 발생할 때만 AOP가 적용됩니다.

자바 객체에서 자기 자신의 메서드를 호출하면 this를 통해서 자기 자신의 인스턴스의 메서드를 직접 호출하므로 프록시 AOP가 호출되지 않습니다. 따라서 1번의 경우에는 @Tx가 있더라도 자기 자신의 메서드를 통해서 호출되기 때문에 AOP가 적용되지 않습니다.

1번: 자기 자신을 호출하므로 트랜잭션 적용 안됨

외부 -> 스프링 AOP(create(request)에는 @Tx가 없으므로 트랜잭션 적용 안함) -> create(request) -> 자기 자신 호출(this)-> @Tx create(originUrl, expire...)

 

2번:

외부 -> 스프링 AOP(create(request)에 @Tx가 있으므로 트랜잭션 적용 함) -> @Tx create(request) -> create(originUrl, expire...)

더 자세한 내용은 스프링 핵심원리 고급편 또는 스프링 DB2편을 참고해주세요 :)

감사합니다.

emkemkemk님의 프로필 이미지
emkemkemk

작성한 질문수

질문하기