Whiteship's Note


하이버네이트 API : Detached 객체 다루기

Hibernate/Chapter 9 : 2008.03.11 15:06


수정된 detached 객체 reattaching 하기

  • update()를 사용하여 새로운 session에 reattach 할 수 있다.
item.setDescription(...); // Loaded in previous Session

Session sessionTwo = sessionFactory.openSession();
Transaction tx = sessionTwo.beginTransaction();

sessionTwo.update(item);

item.setEndDate(...);

tx.commit();
sessionTwo.close();
  • update()에 넘겨주는 객체가 그 전에 수정이 되었는지 안 되었는지는 중요하지 않다.
  • 새로운 Persistent Context에 묶이게 된다는 것이 중요하다.
  • 새로운 Persistent Context에서는 무조건 dirty로 인식하고 나중에 update문을 날리게 된다.
  • DB에서 실제 값과 비교하여 바뀐 부분이 있을 때에만 update문을 날리고 싶으면 select-before-update="true"를 설정한다.
  • 수정되지 않았다는 것이 활실할 때는 update를 사용하지 않는 reattach 방법을 사용한다.

수정되지 않은 detacked 객체를 reattaching 하기

  • lock()을 사용하면 그 시점 부터 DB에 반영을 합니다. 그 이전의 변경 사항은 반영하지 않습니다.
Session sessionTwo = sessionFactory.openSession();
Transaction tx = sessionTwo.beginTransaction();

sessionTwo.lock(item, LockMode.NONE);

item.setDescription(...);
item.setEndDate(...);

tx.commit();
sessionTwo.close();
  • 위에서 사용한 LockMode.NONE은 새로운 객체를 Session에 붙일 때, 버전 확인이나 DB 레벨의 롹을 가져오지 않겠다는 설정입니다.

detacked 객체를 transient 객체로 만들기

  • update()나 lock()를 호출하열 필요 없이 그냥 delete()를 사용합니다.
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();

session.delete(item);

tx.commit();
session.close();
  • 그 안에서 해당 객체를 다시 Session에 붙였다가 tx.commit()이 호출되는 시점에 DB에서 삭제합니다.

detached 객체 mergeing 하기

  • reattachment의 보완제이자 대체제다.
Session session1 = sessionFactory.openSession();
Transaction transaction = session1.beginTransaction();

Member member = new Member();
member.setName("toby");
session1.save(member);

transaction.commit();
session1.close();

member.setName("whiteship");

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

Member member2 = (Member) session2.get(Member.class, member.getId());
Member member3 = (Member) session2.merge(member);

member2.setName("toby");

assertEquals("toby", member3.getName());

transaction2.commit();
session2.close();
  • NonUniqueObjectException: reattack 할 때, 이미 동일한 레코드를 표현하는 객체가 해당 Persistent Context에 존재할 때 발생하는 예외.
  • Persistent Context에 만약, 같은 DB 레코드를 나타내는 객체가 있다면, detached 객체의 값들을 해당 객체로 복사한다.
  • Persistent Context에 존재하지 않는 객체일 경우에는, DB에서 같은 id를 가진 녀석을 읽어온 다음에 merge() 한다.
  • detached객체나, 기존의 Persisitent Context에 있던 객체의 사용은 지양하고, merge()가 반환하는 객체를 사용하도록 한다.
top