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

김대호님의 프로필 이미지
김대호

작성한 질문수

스프링 DB 1편 - 데이터 접근 핵심 원리

정리

entity를 async 메소드 파라미터로 넘길 경우에 대한 질문입니다.

작성

·

597

1

안녕하세요 강사님 항상 좋은강의 잘 보고있습니다.

DB관련 강의를 보고서 코드를 작업하던 중 이해가 안가는 부분이 있어 질문드립니다. 정확한 질문포인트 강의를 찾지 못해 트랜잭션 관련 질문이라 이곳에 남깁니다..

 

Parent entity가 onetomany로 child entity list를 갖고있는 상황입니다. Lazy Loading으로 사용중입니다.

 

@transactional이 붙은 A 메서드가 parent entity를 find해왔습니다. 아직 child를 사용하지 않았습니다. 조회쿼리도 나가지 않았습니다.

 

A메서드는 @Async로 별도 thread에서 동작하는 B메서드에 parentEntity를 parameter로 넘깁니다. (B메서드에는 transactional코드가 없습니다)

 

B메서드에서는 child를 사용하여 동작하는 코드가 들어있습니다.

 

의문점은 이게 fail to lazily initialize... no session이 나와야하지 않나 싶은데 정상작동한다는 점입니다.

 

강의를 통해 제가 이해한것은..

1. transaction은 db connection과 함께 움직입니다.

2. transaction은 thread local로 관리되어 thread마다 할당됩니다. 고로 db connection은 thread에 할당됩니다.

3. entity manager는 일부러 엮지 않는 이상 thread끼리 공유하지 않는다. 한 thread에 하나씩 붙는다.

4. open session in view를 켜지 않는 한 entity manager는 transaction과 생명주기를 같이한다

 

async에서 할당된 thread들은 transaction이 없기 때문에 entity manager를 갖고 있지 않은 상태이고, parameter를 통해 받은 parent entity는 사실상 dto와 같은 취급을 받아야 하는게 아닌가 하는 생각입니다. 고로 parent entity에서 child를 조회하려하면 entity manager와 db connection이 없기 때문에 관련 에러가 터질것이라 생각했습니다.

 

하지만 async 메소드에서 child를 사용하려하면 정상적으로 쿼리가 나가고 실행에 아무런 장애가 없습니다.

 

이에 궁금증이 생겼습니다.

1. entityManager 생성이 transaction과 같이하는게 아니라, Thread가 생성될때마다 각 Thread는 entityManager를 자동으로 부여받는것인가?

2. 1번이 맞다면.. entity가 갖고있는 Lazy loading인 상태의 proxy항목이 Async thread에 있는 entitymanager를 사용해서 조회를한것인가?

parameter로 넘긴 entity가 내부적으로 db connection을 물고있는건가 싶은 의문도 생겼습니다.

 

테스트코드는..

https://github.com/zzangisdaeho/transaction-test.git

TestAsync.testAsync() 를 한번만 봐주실 수 있다면 감사하겠습니다.

(테스트코드 에러는.. 테스트 종료시에 entitymanager를 release하면서 나는 NPE인데.. 아직 원인을 파악하지 못하였습니다. 궁금한점은 async쪽입니다..)

 

감사합니다.

답변 1

4

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

안녕하세요. 김대호님

지연로딩의 경우 엔티티를 통해서 발생하기 때문에 해당 엔티티와 엔티티를 관리하는 영속성 컨텍스트가 살아있다면 정상 동작하게 됩니다.

여기에서 allParent 엔티티를 관리하는 영속성 컨텍스트가 타이밍 상 먼저 죽어버리고, 그 다음에 @Async 내부에서 parent.getChildren().size() 같은 호출이 발생한다면 기대하신 오류를 확인할 수 있습니다.

참고로 실무에서는 이렇게 영속상태로 관리되는 엔티티를 @Async에 넘기는 것은 타이밍상 성공할 수도 있고, 실패할 수도 있기 때문에 권장되지 않는 방법입니다.

감사합니다.

김대호님의 프로필 이미지
김대호

작성한 질문수

질문하기