[JPA] 여러 트랜잭션이 하나의 영속성 컨텍스트?

2024. 7. 31. 01:25·Spring/JPA

스레드는 서버에 요청을 보낸 사용자와 같다.

 

 

난 이 때 까지 JPA를 사용할 때, 하나의 스레드 당 하나의 영속성 컨텍스트를 부여받는다고 생각했다.

 

 

그런데 자바 ORM 표준 JPA 프로그래밍의 15장에서 이 문장을 읽고 머리가 아파졌다.

 

문제는 OSIV처럼 영속성 컨텍스트의 범위를 트랜잭션 범위보다 넓게 사용해서 여러 트랜잭션이 하나의 영속성 컨텍스트를 사용할 때 발생한다.

- 15장, 645페이지

 

 

하지만 스레드와 영속성 컨텍스트의 관계에 대한 정보를 찾아보니까, 아래의 답변 또한 찾을 수 있었다.

 

영속성 컨텍스트는 스레드마다 독립적으로 생성되며, 스레드 간에 공유되지 않습니다. 따라서 개별 스레드에서 동작하는 엔티티 매니저는 각자 독립된 영속성 컨텍스트를 가지게 됩니다.

- 인프런 AI 인턴

 

 

 

내가 생각한 로직은 다음과 같다.

 

 

 

다시 책으로 돌아와서,

 

"문제는 OSIV처럼 영속성 컨텍스트의 범위를 트랜잭션 범위보다 넓게 사용해서 여러 트랜잭션이 하나의 영속성 컨텍스트를 사용할 때 발생한다."

 

 

이 문장을 위의 그림을 토대로 해석하면 다음과 같다.

 

 

  1. 영속성 컨텍스트의 범위를 트랜잭션 범위보다 넓게 사용 -> 영속성 컨텍스트 범위는 프레젠테이션 계층까지 퍼져있는 상태
  2. 여러 트랜잭션이 하나의 영속성 컨텍스트를 사용 -> 한 컨트롤러에서 트랜잭션이 적용된 2개 이상의 메서드를 각각 호출할 경우, 다른 트랜잭션이 적용된다.

 

 

이를 토대로 코드를 작성해봤다.

@Slf4j
@Controller
@RequiredArgsConstructor
public class HomeController {

    private final OrderService orderService;
    private final MemberService memberService;

    @RequestMapping(value = "/test", method = RequestMethod.GET)
    public void home() {
        log.info("첫번째");
        Member findMember = memberService.findById(1L);

        log.info("두번째");
        Order findOrder = orderService.findById(1L);
    }
    
}

 

 

결과 로그는 다음과 같다.

2024-07-31T01:01:48.591+09:00  INFO 82631 --- [nio-8080-exec-1] c.j.ch16.controller.HomeController       : 첫번째
2024-07-31T01:01:48.591+09:00 DEBUG 82631 --- [nio-8080-exec-1] o.s.orm.jpa.JpaTransactionManager        : Found thread-bound EntityManager [SessionImpl(1332011983<open>)] for JPA transaction
2024-07-31T01:01:48.591+09:00 DEBUG 82631 --- [nio-8080-exec-1] o.s.orm.jpa.JpaTransactionManager        : Creating new transaction with name [com.jpabook.ch16.service.MemberService.findById]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
2024-07-31T01:01:48.591+09:00 DEBUG 82631 --- [nio-8080-exec-1] o.s.orm.jpa.JpaTransactionManager        : Exposing JPA transaction as JDBC [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@84c8cbd]
2024-07-31T01:01:48.595+09:00 DEBUG 82631 --- [nio-8080-exec-1] o.s.orm.jpa.JpaTransactionManager        : Initiating transaction commit
2024-07-31T01:01:48.595+09:00 DEBUG 82631 --- [nio-8080-exec-1] o.s.orm.jpa.JpaTransactionManager        : Committing JPA transaction on EntityManager [SessionImpl(1332011983<open>)]
2024-07-31T01:01:48.595+09:00 DEBUG 82631 --- [nio-8080-exec-1] o.s.orm.jpa.JpaTransactionManager        : Not closing pre-bound JPA EntityManager after transaction
2024-07-31T01:01:48.595+09:00  INFO 82631 --- [nio-8080-exec-1] c.j.ch16.controller.HomeController       : 두번째
2024-07-31T01:01:48.595+09:00 DEBUG 82631 --- [nio-8080-exec-1] o.s.orm.jpa.JpaTransactionManager        : Found thread-bound EntityManager [SessionImpl(1332011983<open>)] for JPA transaction
2024-07-31T01:01:48.596+09:00 DEBUG 82631 --- [nio-8080-exec-1] o.s.orm.jpa.JpaTransactionManager        : Creating new transaction with name [com.jpabook.ch16.service.OrderService.findById]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
2024-07-31T01:01:48.596+09:00 DEBUG 82631 --- [nio-8080-exec-1] o.s.orm.jpa.JpaTransactionManager        : Exposing JPA transaction as JDBC [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@404463e2]
2024-07-31T01:01:48.596+09:00 DEBUG 82631 --- [nio-8080-exec-1] o.s.orm.jpa.JpaTransactionManager        : Initiating transaction commit
2024-07-31T01:01:48.596+09:00 DEBUG 82631 --- [nio-8080-exec-1] o.s.orm.jpa.JpaTransactionManager        : Committing JPA transaction on EntityManager [SessionImpl(1332011983<open>)]
2024-07-31T01:01:48.596+09:00 DEBUG 82631 --- [nio-8080-exec-1] o.s.orm.jpa.JpaTransactionManager        : Not closing pre-bound JPA EntityManager after transaction

 

 

로그를 자세히 살펴보면

 

첫번째
Found thread-bound EntityManager [SessionImpl(1332011983<open>)] for JPA transaction
Creating new transaction with name [com.jpabook.ch16.service.MemberService.findById]: ..

 

이 로그의 의미는 스레드에 할당된 엔티티 매니저를 뜻하며 영속성 컨텍스트도 여기에 속하고, 데이터베이스에 접근하기 위해 새로운 트랜잭션을 생성한다. 라는 의미이다.

 

 

두번째
Found thread-bound EntityManager [SessionImpl(1332011983<open>)] for JPA transaction
Creating new transaction with name [com.jpabook.ch16.service.OrderService.findById]: ..

 

이 로그도 위와 동일하다.

 

 

여기서 주목해야 할 점은 두 작업은 모두 새로운 트랜잭션을 생성하여 작업을 수행 한다.

 

 

하지만 영속성 컨텍스트는 Found thread-bound EntityManager [SessionImpl(1332011983)] 를 보다시피 같은 영속성 컨텍스트를 사용한다.

 

 

결론은 영속성 컨텍스트는 요청을 보낸 사용자(스레드) 별로 독립적으로 구성된다. 그렇기 때문에 하나의 영속성 컨텍스트를 사용하는 것 또한 맞는 말이다.

 

 

 

휴 모래성 무너질 뻔!

'Spring > JPA' 카테고리의 다른 글

[JPA] Spring JPA 페이징 성능 향상  (2) 2024.12.24
[JPA] @Embedded, @Embeddable  (0) 2024.07.16
'Spring/JPA' 카테고리의 다른 글
  • [JPA] Spring JPA 페이징 성능 향상
  • [JPA] @Embedded, @Embeddable
오도형석
오도형석
  • 오도형석
    형석이의 성장일기
    오도형석
  • 전체
    오늘
    어제
    • 분류 전체보기 N
      • MSA 모니터링 서비스
        • DB
      • 스파르타 코딩클럽
        • SQL
        • Spring
      • 백엔드
        • Internet
        • Java
        • DB
      • 캡스톤
        • Django
        • 자연어처리
      • Spring
        • JPA
        • MSA
      • ETC
        • ERROR
      • 개발 일기 N
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 인기 글

  • 태그

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
오도형석
[JPA] 여러 트랜잭션이 하나의 영속성 컨텍스트?
상단으로

티스토리툴바