• 카테고리

    질문 & 답변
  • 세부 분야

    백엔드

  • 해결 여부

    미해결

em.find(), select문 질문

23.05.03 12:14 작성 조회수 197

0

em.find(Member.class, 1L);
System.out.println("========================");
tx.commit();

위 코드를 수행한 결과 select문 이후에 '========================'가 출력되었습니다.
em.find()를 하면 우선 1차 캐시에서 엔티티를 찾은 후, 없으면 바로 select문을 DB에 날리는 것이 맞을까요?
tx.commit()하는 시점과 관계없이 1차 캐시에 엔티티가 없으면 바로 select 쿼리를 날리는 것이 맞을까요?

답변 1

답변을 작성해보세요.

0

y2gcoder님의 프로필

y2gcoder

2023.05.03

안녕하세요, 도토리님. 공식 서포터즈 y2gcoder 입니다.

먼저 테스트해주신 전체 코드가 있으면 제가 좀 더 정확하게 대답할 수 있을 것 같습니다.

보여주신 코드와 제가 해당 테스트 코드에 대해 약간의 추측을 한 상태에서 답변을 드려야 할 것 같습니다.

기본적으로 em.find()는 말씀하신대로 영속성 컨텍스트의 1차 캐시에서 먼저 엔티티를 조회하고, 해당 엔티티가 존재하지 않으면 DB에서 조회하는 것이 맞습니다.

위의 코드에서 영속성 컨텍스트를 아예 비운 후에 em.find()를 호출했다고 가정한다면, 말씀드린 절차에 따라 먼저 1차 캐시에서 해당 id를 가진 엔티티를 조회하고, 1차 캐시에 해당 id를 가진 엔티티가 존재하지 않기 때문에 테스트해보신 것처럼 먼저 select 문을 통해 DB에서 해당 엔티티를 조회합니다. 그래서 println() 전에 select 문에 대한 로그가 찍혔을 것으로 보입니다 :)

감사합니다.

도토리님의 프로필

도토리

질문자

2023.05.06

em.persist(), em.remove(), 엔티티 업데이트는 tx.commit()하는 시점에 DB에 각각 insert, delete, update 쿼리가 전달된다고 알고 있습니다. 이들과 다르게 em.find()는 tx.commit()하는 시점이 아니라, em.find()하는 시점에 + 1차 캐시에 해당 엔티티가 없는 경우에 select 쿼리가 전달되는 것이 맞을까요??

y2gcoder님의 프로필

y2gcoder

2023.05.08

맞습니다. EntityManager의 em.persist(), em.remove(), 그리고 엔티티 업데이트는 트랜잭션 커밋(tx.commit())하는 시점에 각각 insert, delete, update 쿼리가 DB로 전달됩니다. 이러한 동작은 변경을 묶어서 한 번에 데이터베이스에 적용하기 위한 것입니다.

반면에 em.find() 메서드는 트랜잭션 커밋 시점과 무관하게 호출되는 즉시 실행됩니다. 다음과 같은 순서로 동작합니다:

  1. em.find()를 호출하면 먼저 1차 캐시에서 해당 엔티티를 찾습니다.

  2. 1차 캐시에 엔티티가 없으면 데이터베이스에서 select 쿼리를 통해 엔티티를 찾습니다.

이러한 동작은 조회 작업을 즉시 수행하여 결과를 제공하기 위한 것입니다.