객체만 생성하면 영속성 컨텍스트나 데이터베이스와 관련없는 비영속 상태이다.
엔티티 매너지가 영속성 컨텍스트에 엔티티 객체를 저장하면 영속성 컨텍스트가 엔티티 객체를 관리하게되고 이를 영속 상태라고 한다.
find()
, JPQL
을 사용한 조회도 영속 상태가된다.
persist(menu)
메소드를 통해 엔터티를 영속
영속성 컨텍스트가 관리하던 엔티티 객체를 관리하지 않는 상태가 된다면 준영속 상태라고 한다.
detach()
: 특정 엔티티만 준영속 상태로 만든다.
clear()
: 영속성 컨텍스트를 초기화. 해당 영속성 컨텍스트의 모든 엔터티를 준영속상태로 만든다. 1차 캐시의 내용이 삭제된다.
close()
:해당 영속성 컨텍스트가 관리하던 영속 상태의 엔터티가 모두 준영속 상태가된다. 1차 캐시 공간 자체가 사라진다.
merge(병합)
를 사용한다.merge()
메소드 : 준영속 상태의 엔티티를 받아서 그 정보로 새로운 영속상태의 엔터티를 반환한다.
준영속 상태의 엔티티가 영속상태로 바뀌는 것은 아니고, 그 값을 받은 새로운 영속 상태의 엔터티가 반환되는 것.
조회할 수 없는 데이터(ex. 비영속 컨텍스트)의 경우 새로 생성해서 병합한다.
병합은 준영속, 비영속 상관없이 식별자값으로 엔터티를 조회할 수 있다면 병합이 가능하다.
조회할수 없다면 새로 생성하는 것.
@Test
public void 병합_merge_수정_테스트() {
//given
Menu menuToDetach = entityManager.find(Menu.class, 2);
entityManager.detach(menuToDetach); //준영속상태로 만듦
System.out.println("menuToDetach1 : " + menuToDetach); //우럭뽈살
//when
menuToDetach.setMenuName("수박죽"); //수박죽 값 넣음
System.out.println("menuToDetach2 : " + menuToDetach); //수박죽
Menu refoundMenu = entityManager.find(Menu.class, 2); //영속상태 우럭뽈살 조회됨
System.out.println("refoundMenu : " + refoundMenu); //우럭뽈살
/* 준영속 엔티티와 영속 엔티티의 해쉬코드는 다른 상태이다. */
System.out.println(menuToDetach.hashCode());
System.out.println(refoundMenu.hashCode());
entityManager.merge(menuToDetach); // 준영속 상태로 만든 것을 다시 병합
//then
Menu mergeMenu = entityManager.find(Menu.class, 2); // menuToDetach가 가진 값만 병합, hash값은 refoundMenu 그대로
assertEquals("수박죽", mergeMenu.getMenuName());
System.out.println("mergeMenu : " + mergeMenu);
System.out.println("menuToDetach Hash : " + menuToDetach.hashCode());
System.out.println("refoundMenu Hash : " + refoundMenu.hashCode());
System.out.println("mergeMenu Hash : " + mergeMenu.hashCode());
}
@Test
public void 병합_merge_삽입_테스트() {
//given
Menu menuToDetach = entityManager.find(Menu.class, 2);
entityManager.detach(menuToDetach);
//when
menuToDetach.setMenuCode(999); //DB에서 조회할 수 없는 키 값으로 변경
menuToDetach.setMenuName("수박죽");
entityManager.merge(menuToDetach); // 영속 상태의 엔티티와 병합(현재는 없기때문에 삽입된다.)
//then
Menu mergeMenu = entityManager.find(Menu.class, 999);
assertEquals("수박죽", mergeMenu.getMenuName());
}
엔티티를 영속성 컨텍스트 및 데이터베이스에서 삭제한다.
단, 트랜젝션을 제어(commit)하지 않으면 영구 반영되지는 않는다.
트랜젝션을 커밋하는 순간 영속성 컨텍스트에서 관리하는 엔티티 객체가 데이터 베이스에 반영되게된다. (이를 flush라한다.)
flush : 영속성 컨텍스트의 변경 내용을 데이터 베이스에 동기화하는 작업(등록, 수정, 삭제한 엔티티를 데이터베이스에 반영)