본문 바로가기

JPA/영속성 관리

#03 영속성 컨텍스트의 특징 - 엔티티 조회

Index

  • 영속성 컨텍스트(persistence context) 의 특징
  • 엔티티 조회

영속성 컨텍스트(persistence context) 의 특징

영속성 컨텍스트와 식별자 값 - 영속성 컨텍스트는 엔티티를 구분하는데 @Id 어노테이션을 붙여놓은 식별자 값으로 구분한다. 따라서 영속 상태는 식별자 값이 반드시 있어야 하고 없으면 예외가 발생한다.

 

테이터베이스 저장 - JPA는 보통 트랜잭션을 커밋하는 순간 영속성 컨텍스트에 새로 저장된 엔티티를 데이터베이스에 반영한다. 그리고 이부분을 flush 라고 한다.

 

영속성 컨텍스트의 장정

  1. 1차 캐시
  2. 동일성 보장
  3. 트랜잭션을 지원하는 쓰기 지연
  4. 변경 감지
  5. 지연 로딩

엔티티 조회

1차 캐시 

영속성 컨텍스트(persistence context)는 내부에 캐시를 가지고 있다 그리고 이것을 1차 캐시라 부르고 영속 상태의 엔티티는 모두 이곳에 저장된다. 그리고 책에서 쉽게 이야기 해준다면서 Map을 예로? 들어 주셨는데 Map에서 Key는 @Id로 매핑한 식별자고 value는 엔티티 인스턴스 라고한다.

        
Member member = new Member();
member.setId("id1");
member.setUsername("홍길동");
member.setAge(2000);

//등록
em.persist(member);

이 코드를 실행하면 member 인스턴스는 영속 컨텍스트 1차 캐시에 저장된다. 

 

1차 캐시 저장 

 

1차 캐시 조회

Member member = new Member();
member.setId("member1");
member.setUsername("홍길동");
member.setAge(2000);

//등록
em.persist(member);

// 조회 (1차 캐시에서 조회된다.)
Member findMember = em.find(Member.class, "member1");

작성된 코드 를 순서대로 읽어보자

1. Member 타입의 member 객체를 만든다.

2. member의 setter 메소드를 이용해서 id/name/age 를 넣어둔다.

3. em.persist(member) 로 EntityManager의 영속성 컨텍스트에 저장한다.(영속상태)

4. em.find() 메소드에 첫번째 인자로 Member.class와 두번쨰 인자로 2번에서 setter 메소들를 이용해서 저장한 Id("member")  를 전달해 준다.

5. EntityManager는 Id를 1차 캐시에서 확인하고 있다면 해당 인스턴스를 return 하게된다. (DB에 접속한게 아님.)

 

 

데이터베이스 조회

em.find() 로 조회를 시도할 때 1차 캐시에 없다면 어떤 방식으로 처리 되는지 확인해 보자 

Entity 조회과정 

1. find("member2")실행해면 "member2" 로 1차 캐시에서 찾아본다.  그러나 존재하지않음

2. 존하지 않기 때문에 DB에 가서 조회 한다. 

3. 조회한 내용으로 member2 의 인스턴스를 생성하고 1차 캐시에 저장한다.

4. 저장한 member2의 인스턴스를 return 한다.

 

잠시 다른 소리긴 하지만 Oracle 에서 SGA의 Buffer Cache 와 유사한 느낌이 든다.  사실 우리가 DB에 쿼리를 날려도 DB에서도 바로 파일에 write 하지않고 Buffer Cache라는 곳에 저장해 뒀다가 한번에 처리를 한다. 뭐 이러한 개념과 비슷한 것 같다.

 

 

영속 엔티티의 동일성 보장

Member a = em.find(Member.class,"member1");
Member b = em.find(Member.class,"member1");

System.out.println( a == b); // 동일성 비교

결과 : true

 

둘의 결과가 true로 나와서 동일성이 보장된다는 부분을 잘 생각해 보면 1차 캐시에 저장된 인스턴스를 반환하기 때문에 당연히 Heap 영역에 같은 메모리를 참조 하므로 "member1" 으로  find() 하면 몇번을 해도 true가 보장된다.

 

자바에서는 같다는걸 비교할 때 주로 Obejct 클래스의 equals() 메소드를 재정의 해서 사용하거나 이미 재정의 되어 있는 equals() 를 사용하게 된다.  그렇다면 Equals()로 비교하지 않은 이유는??  인스턴스가 서로 같은지를 보기위함이다. 

그래서 책에서는 인스턴스 끼리 같은지 보는 부분을 동일성 으로 이야기 하고 있으며 실제 value가 같은지 보는걸 동등성 이라고 이야기 하고 있다.

 

동일성(identity) : 실제 인스턴스가 같다. 따라서 참조 값을 비교하는 == 비교의 값이 같다.

동등성(equality) : 실제 인스턴스는 다를 수 있지만 인스턴스가 가지고 있는 값이 같다. 자바에서 동등성 비교는 equals() 메소드를 구현해야 한다.

 

 

글이 너무 길어 지는 관계로 엔티티의 등록 / 수정 / 삭제는 다음포스팅에서...