티스토리 뷰
Entity 조회
Service 레이어에서 DB에 접근할 때 Transaction 단위로 수행됩니다.
예를 들어, Member 테이블에 id 값이 1인 엔티티가 존재합니다. 해당 엔티티를 조회하기 위해서는 Transaction 단위로 조회해야 합니다.
DB에서 엔티티를 조회하기 위해 MemberService를 정의합니다. MemberRepository를 의존성 주입을 받아 사용합니다.
@Service
public class MemberService {
@Autowired
MemberRepository memberRepository;
@Transactional(readOnly = true)
public Member findMember(Long id) {
return memberRepository.findById(id).orElseThrow(() -> new IllegalArgumentException("해당 사용자가 없습니다."));
}
}
Controller에서 MemberService를 사용하여 id가 1인 엔티티를 조회해보겠습니다.
@RestController
@Slf4j
public class MemberController {
@Autowired
MemberService memberService;
@GetMapping("/{id}")
public Member findMember(@PathVariable Long id) {
Member member = memberService.findMember(id);
log.info("member={}", member);
return member;
}
}
조회 결과는 다음과 같습니다.
member=com.example.demo.entity.Member@7fe6a969
이번에는 서로 다른 트랜잭션에서 id가 1인 엔티티를 조회하고, 두 엔티티가 동일한지 비교해보겠습니다.
@RestController
@Slf4j
public class MemberController {
@Autowired
MemberService memberService;
@GetMapping("/{id}")
public Member findMember(@PathVariable Long id) {
Member m1 = memberService.findMember(id);
Member m2 = memberService.findMember(id);
log.info("m1 = {}, m2 = {}", m1, m2);
log.info("m1 == m2 : {}", m1 == m2);
return m1;
}
}
m1과 m2의 조회결과는 다음과 같습니다.
m1 = com.example.demo.entity.Member@7fe6a969
m2 = com.example.demo.entity.Member@425ecb49
m1 == m2 : false
m1과 m2가 서로 다른 주소 값을 갖기 때문에 서로 다른 객체로 인식하게 됩니다. 분명 동일한 id값을 갖는 엔티티를 조회하였는데 왜 다른 객체로 조회가 되는 것일까요? 정답은 서로 다른 Transaction에서 조회되었기 때문입니다.
Transaction과 1차 캐시
1차 캐시는 Transaction 범위 내에서만 유지되는 캐시입니다. 즉, 특정 Transaction 내에서 엔티티를 조회하면 그 결과가 1차 캐시에 저장되고, 같은 Transaction 범위 내에서 동일한 id를 갖는 엔티티를 다시 조회하면 DB를 접근할 필요 없이 1차 캐시에서 가져와서 사용하게 됩니다.
그러나 서로 다른 Transaction에서 조회된 엔티티는 자신만의 1차 캐시를 가지게 됩니다. 즉, 동일한 id를 갖는 엔티티를 조회하더라도 다른 Transaction에서 조회하였더라면 다른 객체로 인식하게 되는 것입니다.
JPA가 트랜잭션의 격리 수준을 유지하는 이유는 데이터의 일관성을 유지하기 위해서입니다. 각 트랜잭션이 독립적으로 데이터를 관리하고 변경할 수 있도록 하여, 한 트랜잭션의 변경이 다른 트랜잭션으로 영향을 주지 않도록 하기 위해서입니다.
결론
서로 다른 트랜잭션에서 id가 동일한 엔티티를 조회하면 JPA는 다른 객체로 인식한다. 그 이유는 서로 다른 1차 캐시에서 엔티티가 관리되기 때문이다.