Whiteship's Note


[하이버네이트] detached 객체의 동일성

Hibernate/Chapter 9 : 2009.06.25 13:54


참조: JPWH 9.2.2 ~ 9.2.3

두 가지 동일성이 있다. 자바 객체 동일성과 DB 동일성이 있다. 자바 동일성은 == 으로 비교를 하고, DB 동일성은 주키 값을 비교한다. 자바 동일성과 DB 동일성이 모두 같을 조건을 Scope of object identity 라고 한다.

그 중에 세 가지 조건은 다음과 같다.
- No identity scope
- Persistence context-scoped identity
- Process-scoped identity

이 중에 하이버네이트는 Persistence context-scoped identity를 구현했다.

Session session1 = sessionFactory.openSession();
Transaction tx1 = session1.beginTransaction();

// "1234" 식별자로 Item 가져오기
Object a = session1.get(Item.class, new Long(1234) );
Object b = session1.get(Item.class, new Long(1234) );

( a==b ) // True, a와 b는 동일하다.
tx1.commit();
session1.close();

// a와 b 레퍼런스는 detached 상태 객체가 된다.

Session session2 = sessionFactory.openSession();
Transaction tx2 = session2.beginTransaction();

Object c = session2.get(Item.class, new Long(1234) );
( a==c ) // False, detached 객체 a와 persistent 객체 c는 동일하지 않다.(session context가 다르기 때문에..)

tx2.commit();
session2.close();

따라서 이렇게 된다. 하지만 여전히 DB id는 가지고 있기 때문에, a, b, c를 id 값으로 비교하면 모두 같은 객체로 인식할 수 있다. equlas()로 비교할 땐 equals()를 어떻게 구현하느냐에 따라 달리질 것이다. equals()를 별도로 구현하지 않으면 Object의 equals()를 사용할테니 == 비교와 다를 바가 없다.

equals() 비교가 중요해지는 시기는 Set 컬렉션을 사용할 때다. 아시다시피 Set은 컬렉션에 요소를 추가하기 전에 기본에 추가되어 있는 것들과 equals() 비교를 해본 다음에 false인 것만 추가한다.

그렇다면, 위의 코드가 모두 깥는 뒤 (detached) 객체 3개(a, b, c)를 Set에 추가하면 어떻게 될까? 과연 Set에는 몇 개의 객체가 들어갈까?

2개다. 일단, equals()를 별도로 구현하지 않아서, == 비교를 할 텐데 이미 위에서 == 비교를 해봤더니 a와 b는 같은 객체를 참조하고 있고, c는 또 다른 객체기 때문이다.

원하던 결과는 몇 개 일까? 한 개일 것이다. 셋 다 같은 DB 레코드를 가리키기 때문에, Set에는 한 개만 들어가는게 맞을 것이다. 그렇게 하려면 어떻게 해야 할까?

DB id를 사용해서 동일성을 비교하는 equals()를 재정의하면 될 것이다. equals()를 재정의하면 hashCode()도 반드시 재정의해서 같은 객체는 같은 해쉬코드를 반환하도록 해야겠다.

결론적으로, detached 객체를 다룰 때는 동일성에 주의하고, 동일성 문제가 발생할 시 equals()와 hashCode()를 적절하게 재정의 할 것.




top


객체 상태

Hibernate/Chapter 9 : 2008.02.24 13:56


특징

  • ORM 솔루션마다 서로 다른 용어와 서로 다른 상태를 정의하고 영속성 라이프사이클의 상태 전이를 다룬다.
  • 하이버네이트는 네 가지 상태를 가지고 있다.

  • 이탤릭체의 메소드 이름은 JPA의 EntityManager와 Hibernate의 Session에서 공통으로 사용할 수 있는 API

Transient Object

  • new 연산자를 사용하여 생성한 객체는 곧바로 persistent 상태가 되지 않는다.
  • 데이터베이스의 레코드와 아무 연관이 없기 때문에, 메모리에서 없어지면 그 상태 정보도 없어진다.
  • JPA에는 이 상태를 나타내는 용어가 없다.
  • 이 상태의 객체는 nontransactional로, Persistence Context에 변경 사항이 기록되지 않는다. 따라서 롤백을 지원하지 않는다.
  • 이 상태의 객체가 참조하는 객체들도 기본적으로는 Transient 상태다.

Persistent Object

  • 데이터베이스 식별자를 가지고 있는 엔티티다.
  • Persistent 상태의 객체에 의해 참조되었기 때문에 이 상태가 되는 객체도 있다.
  • DB에서 쿼리, 식별자 룩업, 다른 Pesistent 객체로 부터 시작한 객체 그래프 네비게이션 등을 통해서 이 상태가 되는 객체도 있다.
  • 이 상태의 객체는 항상 Persistent Context와 연관을 맺고 있다.
  • 하이버네이트는 그들을 캐쉬하고 애플리케이션 내에서의 변경 사항을 감지할 수 있다.

Removed Object

  • 엔티티 개체를 여러 방법으로 제거할 수 있다.
  • Persistent Manager의 메소드를 사용하여 제거할 수 있다.
  • Orpahn Deletion(해당 하는 객체를 참조하는 녀석이 없을 때 지우기)을 할 수 있다.
  • Unit of work가 끝나면 곧 사라질 객체지만 여전히 Persistent Context에는 남아있을 수 있다.
  • 따라서, 애플리케이션 내에서 해당 객체에 대한 참조를 모두 제거해야 한다.

Detached Object

  • Unit of work를 마친 뒤에 여전히 애플리케이션에서 참조되고 있는 객체.
  • Persistent Context가 활성화 되어 있을 동안 만 Persistent 상태였다.
  • 이 상태의 객체들은 더이상 DB와 동기화 하지 않는다.
  • Persistent Context에 연관되어 있지 않다.
  • 이 상태의 객체를 가지고 여러 변경 작업을 할 수 있고, 후에 다시 Persistent 상태로 돌리고 싶을 수 있다.
  • 하이버는 그런 상황을 위해 reattachment와 merging을 제공한다.
  • JP는 오직 merging만 표준화했다.
  • Conversation: long units of work

'Hibernate > Chapter 9' 카테고리의 다른 글

하이버네이트 API : Persistence context 관리하기  (0) 2008.03.11
하이버네이트 API : Detached 객체 다루기  (0) 2008.03.11
하이버네이트 API: 저장하고 읽어들이기  (0) 2008.03.11
Reattaching과 Merging  (2) 2008.03.11
Persistence context 확장하기  (0) 2008.02.24
The identity of detached objects  (0) 2008.02.24
The Scope of Object Identity  (0) 2008.02.24
Conversation 소개  (0) 2008.02.24
Persistence Context  (0) 2008.02.24
객체 상태  (0) 2008.02.24
Persistence Lifecycle  (0) 2008.02.24
top