하이버네이트 API : Detached 객체 다루기
수정된 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()가 반환하는 객체를 사용하도록 한다.